Pārlūkot izejas kodu

Added constraint checking.

Lacey Sanderson 6 gadi atpakaļ
vecāks
revīzija
50d6dbb155

+ 41 - 2
tests/tripal_chado/api/ChadoComplianceTest.php

@@ -62,7 +62,6 @@ class ChadoComplianceTest extends TripalTestCase {
 
     // Retrieve the schema for this table.
     $table_schema = $chado_schema->getTableSchema($table_name);
-    //print "Table ($table_name)! " . print_r($table_schema,TRUE) . "\n";
 
     // For each column in this table...
     foreach ($table_schema['fields'] as $column_name => $column_details) {
@@ -83,10 +82,50 @@ class ChadoComplianceTest extends TripalTestCase {
       );
     }
 
-    // For each constraint on this table...
+    // There are three types of constraints:
+    // primary key, unique keys, and foreign keys.
+    //.......................................
+
+    // For the primary key:
+    // Check #4: The constraint exists.
+    $pkey_column = $table_schema['primary key'][0];
+    $this->assertTrue(
+      $chado_schema->checkPrimaryKey($table_name, $pkey_column),
+      t('The column "!table.!column" must have an associated sequence attached for chado v!version.',
+        array('!column' => $pkey_column, '!table' => $table_name, '!version' => $version))
+    );
+
+    // For each unique key:
+    foreach ($table_schema['unique keys'] as $constraint_name => $columns) {
+      // @debug print "Check '$constraint_name' for '$table_name': ".implode(', ', $columns).".\n";
 
       // Check #4: The constraint exists.
+      $this->assertTrue(
+        $chado_schema->checkConstraintExists($table_name, $constraint_name, 'UNIQUE'),
+        t('The unique constraint "!name" for "!table" must exist for chado v!version.',
+          array('!name' => $constraint_name, '!table' => $table_name, '!version' => $version))
+      );
 
       // Check #5: The constraint consists of the columns we expect.
+      // @todo
+    }
+
+    // For each foreign key:
+    foreach ($table_schema['foreign keys'] as $fk_table => $details) {
+      foreach ($details['columns'] as $base_column => $fk_column) {
+        // @debug print "Check '$table_name.$base_column =>  $fk_table.$fk_column ' foreign key.";
+
+        // Check #4: The constraint exists.
+        $this->assertTrue(
+          $chado_schema->checkFKConstraintExists($table_name, $base_column, 'FOREIGN KEY'),
+          t('The foreign key constraint "!name" for "!table.!column" must exist for chado v!version.',
+            array('!name' => $constraint_name, '!table' => $table_name,
+              '!column' => $column_name, '!version' => $version))
+        );
+
+        // Check #5: The constraint consists of the columns we expect.
+        // @todo
+      }
+    }
   }
 }

+ 113 - 7
tripal_chado/api/ChadoSchema.inc

@@ -455,20 +455,126 @@ class ChadoSchema {
   }
 
   /**
-   * Check that any given column in a Chado table exists.
+   * Check that any given sequence in a Chado table exists.
    *
-   * This function is necessary because Drupal's db_field_exists() will not
-   * look in any other schema but the one were Drupal is installed
+   * @param table
+   *   The name of the table the sequence is used in.
+   * @param column
+   *   The name of the column the sequence is used to populate.
    *
-   * @param sequence
-   *   The name of the sequence
    * @return
    *   TRUE if the seqeuence exists in the chado schema and FALSE if it does not.
    *
    * @ingroup tripal_chado_schema_api
    */
-  public function checkSequenceExists($sequence) {
-    return chado_sequence_exists($sequence);
+  public function checkSequenceExists($table, $column) {
+
+    $prefixed_table = $this->schema_name.'.'.$table;
+    $sequence_name = db_query('SELECT pg_get_serial_sequence(:table, :column);',
+      array(':table' => $prefixed_table, ':column' => $column))->fetchField();
+
+
+    // Remove prefixed table from sequence name
+    $sequence_name = str_replace($this->schema_name.'.', '', $sequence_name);
+
+    return chado_sequence_exists($sequence_name);
+  }
+
+  /**
+   * Check that the primary key exists, has a sequence and a constraint.
+   *
+   * @param $table
+   *   The table you want to check the primary key for.
+   * @param $column
+   *   (OPTIONAL) The name of the primary key column.
+   *
+   * @return
+   *   TRUE if the primary key meets all the requirements and false otherwise.
+   */
+  function checkPrimaryKey($table, $column = NULL) {
+
+    // If they didn't supply the column, then we can look it up.
+    if ($column === NULL) {
+      $table_schema = $this->getTableSchema($table);
+      $column = $table_schema['primary key'][0];
+    }
+
+    // Check the column exists.
+    $column_exists = $this->checkColumnExists($table, $column);
+    if (!$column_exists) {
+      return FALSE;
+    }
+
+    // First check that the sequence exists.
+    $sequence_exists = $this->checkSequenceExists($table, $column);
+    if (!$sequence_exists) {
+      return FALSE;
+    }
+
+    // Next check the constraint is there.
+    $constraint_exists = chado_query(
+      "SELECT 1
+      FROM information_schema.table_constraints
+      WHERE table_name=:table AND constraint_type = 'PRIMARY KEY'",
+      array(':table' => $table))->fetchField();
+    if (!$constraint_exists) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * Check that the constraint exists.
+   *
+   * @param $table
+   *   The table the constraint applies to.
+   * @param $constraint_name
+   *   The name of the constraint you want to check.
+   * @param $type
+   *   The type of constraint. Should be one of "PRIMARY KEY", "UNIQUE", or "FOREIGN KEY".
+   *
+   * @return
+   *   TRUE if the constraint exists and false otherwise.
+   */
+  function checkConstraintExists($table, $constraint_name, $type) {
+
+    // Next check the constraint is there.
+    $constraint_exists = chado_query(
+      "SELECT 1
+      FROM information_schema.table_constraints
+      WHERE table_name=:table AND constraint_type = :type AND constraint_name = :name",
+      array(':table' => $table, ':name' => $constraint_name, ':type' => $type))->fetchField();
+    if (!$constraint_exists) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * Check the foreign key constrain specified exists.
+   *
+   * @param $base_table
+   *   The name of the table the foreign key resides in. E.g. 'feature' for
+   *     the feature.type_id => cvterm.cvterm_id foreign key.
+   * @param $base_column
+   *   The name of the column that is a foreign key in. E.g. 'type_id' for
+   *     the feature.type_id => cvterm.cvterm_id foreign key.
+   *
+   * @return
+   *   TRUE if the constraint exists and false otherwise.
+   */
+  function checkFKConstraintExists($base_table, $base_column) {
+
+
+    // Since we don't have a constraint name, we have to use the known pattern for
+    // creating these names in order to make this check.
+    // This is due to PostgreSQL not storing column information for constraints
+    // in the information_schema tables.
+    $constraint_name = $base_table . '_' . $base_column . '_fkey';
+
+    return $this->checkConstraintExists($base_table, $constraint_name, 'FOREIGN KEY');
   }
 
   /**