Browse Source

Merge branch '6.x-1.x' of git.drupal.org:sandbox/spficklin/1337878 into 6.x-1.x

Lacey Sanderson 12 years ago
parent
commit
36f80a9adf
2 changed files with 787 additions and 373 deletions
  1. 427 168
      tripal_core/api/tripal_core.api.inc
  2. 360 205
      tripal_feature/includes/gff_loader.inc

+ 427 - 168
tripal_core/api/tripal_core.api.inc

@@ -117,17 +117,37 @@ require_once "tripal_core.schema_v1.11.api.inc";
  * @ingroup tripal_chado_api
  */
 function tripal_core_chado_insert($table, $values, $options = array()) {
-  $insert_values = array();
 
-  // we need to get a persistent connection.  If one exists this function
-  // will not recreate it, but if not it will create one and store it in
-  // a Drupal variable for reuse later.
-  tripal_db_persistent_chado();
+  // set defaults for options. If we don't set defaults then
+  // we get memory leaks when we try to access the elements
+  if (!is_array($options)) {
+    $options = array();
+  }
+  if (!array_key_exists('is_prepared', $options)) {
+    $options['is_prepared'] = FALSE;
+  }
+  if (!array_key_exists('statement_name',$options)) {
+    $options['statement_name'] = FALSE;
+  }
+  if (!array_key_exists('skip_validation',$options)) {
+    $options['skip_validation'] = FALSE;
+  }
+  
+  $insert_values = array();
 
   // Determine plan of action
   if ($options['statement_name']) {
     // we have a prepared statment (or want to create one) so set $prepared = TRUE
     $prepared = TRUE;
+    
+    // we need to get a persistent connection.  If one exists this function
+    // will not recreate it, but if not it will create one and store it in
+    // a Drupal variable for reuse later.
+    $connection = tripal_db_persistent_chado();
+  }
+  else {
+     print "NO STATEMENT (insert): $table\n";
+     debug_print_backtrace();
   }
 
   if (array_key_exists('skip_validation', $options)) {
@@ -148,8 +168,16 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
   // resolved.
   foreach ($values as $field => $value) {
     if (is_array($value)) {
+      $foreign_options = array();
+      if ($options['statement_name']) {
+        // add the fk relationship info to the prepared statement name so that
+        // we can prepare the selects run by the recrusive tripal_core_chado_get_foreign_key
+        // function.
+        $foreign_options['statement_name'] = "fk_" . $table . "_" . $field;
+      }
       // select the value from the foreign key relationship for this value
-      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value);
+      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value, $foreign_options);
+      
       if (sizeof($results) > 1) {
         watchdog('tripal_core', 'tripal_core_chado_insert: Too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
       }
@@ -175,11 +203,12 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
       foreach ($ukeys as $name => $fields) {
         foreach ($fields as $index => $field) {
           // build the arrays for performing a select that will check the contraint
-          array_push($ukselect_cols, $field);
+          $ukselect_cols[] = $field;
           $ukselect_vals[$field] = $insert_values[$field];
         }
         // now check the constraint
-        if (tripal_core_chado_select($table, $ukselect_cols, $ukselect_vals)) {
+        $coptions = array('statement_name' => 'uqsel_' . $table . '_' . implode('_',$ukselect_cols));
+        if (tripal_core_chado_select($table, $ukselect_cols, $ukselect_vals, $coptions)) {
           watchdog('tripal_core', "tripal_core_chado_insert: Cannot insert duplicate record into $table table: " . print_r($values, 1), array(), 'WATCHDOG_ERROR');
           return FALSE;
         }
@@ -189,7 +218,8 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
     // if trying to insert a field that is the primary key, make sure it also is unique
     $pkey = $table_desc['primary key'][0];
     if ($insert_values[$pkey]) {
-      if (tripal_core_chado_select($table, array($pkey), array($pkey => $insert_values[$pkey]))) {
+      $coptions = array('statement_name' => 'pqsel_' . $table . '_' . $pkey);
+      if (tripal_core_chado_select($table, array($pkey), array($pkey => $insert_values[$pkey]), $coptions)) {
         watchdog('tripal_core', "tripal_core_chado_insert: Cannot insert duplicate primary key into $table table: " . print_r($values, 1), array(), 'WATCHDOG_ERROR');
         return FALSE;
       }
@@ -211,11 +241,11 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
   } //end of validation
 
   // Now build the insert SQL statement
-  $ifields = array(); //contains the names of the fields
-  $ivalues = array(); //contains the values of the fields
-  $itypes = array(); // contains %d/%s placeholders for the sql query
+  $ifields = array();       // contains the names of the fields
+  $ivalues = array();       // contains the values of the fields
+  $itypes = array();        // contains %d/%s placeholders for the sql query
   $iplaceholders = array(); // contains $1/$2 placeholders for the prepare query
-  $idatatypes = array(); //contains the data type of the fields (int, text, etc.)
+  $idatatypes = array();    // contains the data type of the fields (int, text, etc.)
   $i = 1;
   foreach ($insert_values as $field => $value) {
     $ifields[] = $field;
@@ -227,8 +257,8 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
       $idatatypes[] = "NULL";
     }
     elseif (strcasecmp($table_desc['fields'][$field]['type'], 'serial')==0 OR
-      strcasecmp($table_desc['fields'][$field]['type'], 'int')==0 OR
-      strcasecmp($table_desc['fields'][$field]['type'], 'integer')==0) {
+            strcasecmp($table_desc['fields'][$field]['type'], 'int')==0 OR
+            strcasecmp($table_desc['fields'][$field]['type'], 'integer')==0) {
       $itypes[] = "%d";
       $idatatypes[] = 'int';
     }
@@ -236,6 +266,10 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
       $itypes[] = "%s";
       $idatatypes[] = 'bool';
     }
+    elseif (strcasecmp($table_desc['fields'][$field]['type'], 'float')==0) {
+      $itypes[] = "%s";
+      $idatatypes[] = 'numeric';
+    }
     else {
       $itypes[] = "'%s'";
       $idatatypes[] = 'text';
@@ -292,22 +326,33 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
   return FALSE;
 
 }
-
 /**
- * Provides a generic function for deleting a record(s) from any chado table
+ * Provides a generic routine for updating into any Chado table
  *
- * Use this function to delete a record(s) in any Chado table.  The first
- * argument specifies the table to delete from and the second is an array
- * of values to match for locating the record(s) to be deleted.  The arrays
- * are mutli-dimensional such that foreign key lookup values can be specified.
+ * Use this function to update a record in any Chado table.  The first
+ * argument specifies the table for inserting, the second is an array
+ * of values to matched for locating the record for updating, and the third
+ * argument give the values to update.  The arrays are mutli-dimensional such
+ * that foreign key lookup values can be specified.
  *
  * @param $table
  *  The name of the chado table for inserting
  * @param $match
  *  An associative array containing the values for locating a record to update.
- *
+ * @param $values
+ *  An associative array containing the values for updating.
+ * @param $options
+ *  An array of options such as:
+ *  - statement_name: the name of the prepared statement to use. If the statement
+ *     has not yet been prepared it will be prepared automatically. On subsequent
+ *     calls with the same statement_name only an execute on the previously
+ *     prepared statement will occur.
+ *  - is_prepared: TRUE or FALSE. Whether or not the statement is prepared. By
+ *     default if the statement is not prepared it will be automatically.
+ *     However to avoid this check, which requires a database query you can
+ *     set this value to true and the check will not be performed.
  * @return
- *   On success this function returns TRUE. On failure, it returns FALSE.
+ *  On success this function returns TRUE. On failure, it returns FALSE.
  *
  * Example usage:
  * @code
@@ -338,17 +383,46 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
  *   $result = tripal_core_chado_update('feature',$umatch,$uvalues);
  * @endcode
  * The above code species that a feature with a given uniquename, organism_id,
- * and type_id (the unique constraint for the feature table) will be deleted.
+ * and type_id (the unique constraint for the feature table) will be updated.
  * The organism_id is specified as a nested array that uses the organism_id
  * foreign key constraint to lookup the specified values to find the exact
  * organism_id. The same nested struture is also used for specifying the
- * values to update.  The function will find all records that match the
- * columns specified and delete them.
+ * values to update.  The function will find the record that matches the
+ * columns specified and update the record with the avlues in the $uvalues array.
  *
  * @ingroup tripal_chado_api
  */
-function tripal_core_chado_delete($table, $match) {
-  $delete_matches = array();  // contains the values for the where clause
+function tripal_core_chado_update($table, $match, $values, $options = NULL) {
+
+  // set defaults for options. If we don't set defaults then
+  // we get memory leaks when we try to access the elements
+  if (!is_array($options)) {
+    $options = array();
+  }
+  if (!array_key_exists('is_prepared', $options)) {
+    $options['is_prepared'] = FALSE;
+  }
+  if (!array_key_exists('statement_name',$options)) {
+    $options['statement_name'] = FALSE;
+  }
+
+  $update_values = array();   // contains the values to be updated
+  $update_matches = array();  // contains the values for the where clause
+  
+  // Determine plan of action
+  if ($options['statement_name']) {
+    // we have a prepared statment (or want to create one) so set $prepared = TRUE
+    $prepared = TRUE;
+    
+    // we need to get a persistent connection.  If one exists this function
+    // will not recreate it, but if not it will create one and store it in
+    // a Drupal variable for reuse later.
+    $connection = tripal_db_persistent_chado();
+  }
+  else {
+     print "NO STATEMENT (update): $table\n";
+     debug_print_backtrace();
+  }
 
   // get the table description
   $table_desc = tripal_core_get_chado_table_schema($table);
@@ -356,87 +430,249 @@ function tripal_core_chado_delete($table, $match) {
   // get the values needed for matching in the SQL statement
   foreach ($match as $field => $value) {
     if (is_array($value)) {
-      // if the user has specified an array of values to delete rather than
-      // FK relationships the keep those in our match
-      if (array_values($value) === $value) {
-        $delete_matches[$field] = $value;
+      $foreign_options = array();
+      if ($options['statement_name']) {
+        // add the fk relationship info to the prepared statement name so that
+        // we can prepare the selects run by the recrusive tripal_core_chado_get_foreign_key
+        // function.
+        $foreign_options['statement_name'] =  "fk_" . $table . "_" . $field;
+      }
+      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value, $foreign_options);
+      if (sizeof($results) > 1) {
+        watchdog('tripal_core', 'tripal_core_chado_update: When trying to find record to update, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
+      }
+      elseif (sizeof($results) < 1) {
+        //watchdog('tripal_core', 'tripal_core_chado_update: When trying to find record to update, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
       }
       else {
-        $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value);
-        if (sizeof($results) > 1) {
-          watchdog('tripal_core', 'tripal_core_chado_delete: When trying to find record to delete, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
-        }
-        elseif (sizeof($results) < 1) {
-          //watchdog('tripal_core', 'tripal_core_chado_delete: When trying to find record to delete, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value,TRUE)), WATCHDOG_ERROR);
-        }
-        else {
-          $delete_matches[$field] = $results[0];
-        }
+        $update_matches[$field] = $results[0];
       }
     }
     else {
-      $delete_matches[$field] = $value;
+      $update_matches[$field] = $value;
     }
   }
 
-  // now build the SQL statement
-  $sql = "DELETE FROM {$table} WHERE ";
-  $dargs = array();
-  foreach ($delete_matches as $field => $value) {
-    if (count($value) > 1) {
-      $sql .= "$field IN (" . db_placeholders($value, 'varchar') . ") AND ";
-      foreach ($value as $v) {
-        $dargs[] = $v;
+  // get the values used for updating
+  foreach ($values as $field => $value) {
+    if (is_array($value)) {
+      $foreign_options = array();
+      // select the value from the foreign key relationship for this value
+      if ($options['statement_name']) {
+         // add the fk relationship info to the prepared statement name so that
+         // we can prepare the selects run by the recrusive tripal_core_chado_get_foreign_key
+         // function.
+         $foreign_options['statement_name'] = "fk_" . $table . "_" . $field;
+      }
+      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value, $foreign_options);
+      if (sizeof($results) > 1) {
+        watchdog('tripal_core', 'tripal_core_chado_update: When trying to find update values, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
+      }
+      elseif (sizeof($results) < 1) {
+        //watchdog('tripal_core', 'tripal_core_chado_update: When trying to find update values, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value,TRUE)), WATCHDOG_ERROR);
+      }
+      else {
+        $update_values[$field] = $results[0];
       }
     }
     else {
+      $update_values[$field] = $value;
+    }
+  }
+
+  // now build the SQL statement
+  $sql  = "UPDATE {$table} SET ";
+  $psql = "UPDATE {$table} SET ";
+  $uargs = array();
+  $idatatypes = array();
+  $pvalues = array();
+  $ivalues = array();
+  $i = 1;
+  foreach ($update_values as $field => $value) {
+    
+    if (strcasecmp($table_desc['fields'][$field]['type'], 'serial')==0 OR
+        strcasecmp($table_desc['fields'][$field]['type'], 'int')==0 OR
+        strcasecmp($table_desc['fields'][$field]['type'], 'integer')==0) {
       if (strcmp($value, '__NULL__') == 0) {
-        $sql .= " $field = NULL AND ";
+        $sql .= " $field = %s, ";
+        $ivalues[] = 'NULL';
+        $pvalues[] = '%s';
+        $uargs[] = 'NULL';
       }
-      elseif (strcmp($fields[$field]['type'], 'serial') == 0 or
-        strcmp($fields[$field]['type'], 'int') == 0) {
+      else {
+        $sql .= " $field = %d, ";
+        $ivalues[] = $value;
+        $pvalues[] = '%d';
+        $uargs[] = $value;
+      }
+      $idatatypes[] = 'int';
+      
+    }
+    elseif (strcasecmp($table_desc['fields'][$field]['type'], 'boolean')==0) {
+      $sql .= " $field = %s, ";   
+      $pvalues[] = '%s';   
+      if (strcmp($value, '__NULL__')==0) {
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+      } 
+      else {
+        $ivalues[] = $value;
+        $uargs[] = $value;
+      }
+      $idatatypes[] = 'bool';
+    }
+    elseif (strcasecmp($table_desc['fields'][$field]['type'], 'float')==0) {
+      $sql .= " $field = %s, "; 
+      $pvalues[] = '%s';     
+      if (strcmp($value, '__NULL__')==0) {
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+      } 
+      else {
+        $ivalues[] = $value;
+        $uargs[] = $value;
+      }
+      $idatatypes[] = 'numeric';
+    }
+    else {      
+      if (strcmp($value, '__NULL__') == 0) {
+        $sql .= " $field = %s, ";
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+        $pvalues[] = '%s';
+      }
+      else {
+        $sql .= " $field = '%s', ";
+        $ivalues[] = $value;
+        $uargs[] = $value;
+        $pvalues[] = "'%s'";
+      }
+      $idatatypes[] = 'text';
+    }
+    $psql .= "$field = \$" . $i . ", ";
+    $i++;
+  }
+  $sql = drupal_substr($sql, 0, -2);  // get rid of the trailing comma & space
+  $psql = drupal_substr($psql, 0, -2);  // get rid of the trailing comma & space
+  
+  $sql .= " WHERE ";
+  $psql .= " WHERE ";
+  foreach ($update_matches as $field => $value) {
+    
+    if (strcasecmp($table_desc['fields'][$field]['type'], 'serial')==0 OR
+        strcasecmp($table_desc['fields'][$field]['type'], 'int')==0 OR
+        strcasecmp($table_desc['fields'][$field]['type'], 'integer')==0) {
+      if (strcmp($value, '__NULL__')==0) {
+        $sql .= " $field = %s AND ";
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+        $pvalues[] = '%s';
+      } 
+      else {
         $sql .= " $field = %d AND ";
+        $ivalues[] = $value;
+        $uargs[] = $value; 
+        $pvalues[] = '%s';       
+      }
+      $idatatypes[] = 'int';     
+    }
+    elseif (strcasecmp($table_desc['fields'][$field]['type'], 'boolean')==0) {
+      $sql .= " $field = %s AND ";     
+      $pvalues[] = '%s'; 
+      if (strcmp($value, '__NULL__')==0) {
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+      } 
+      else {
+        $ivalues[] = $value;
+        $uargs[] = $value;
+      }
+      $idatatypes[] = 'bool';
+    }
+    elseif (strcasecmp($table_desc['fields'][$field]['type'], 'float')==0) {
+      $sql .= " $field = %s AND ";
+      $pvalues[] = '%s';      
+      if (strcmp($value, '__NULL__')==0) {
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+      } 
+      else {
+        $ivalues[] = $value;
+        $uargs[] = $value;
+      }
+      $idatatypes[] = 'numeric';
+    }
+    else {      
+      if (strcmp($value, '__NULL__')==0) {
+        $sql .= " $field = %s AND ";
+        $ivalues[] = 'NULL';
+        $uargs[] = 'NULL';
+        $pvalues[] = '%s';
       }
       else {
         $sql .= " $field = '%s' AND ";
+        $ivalues[] = $value;
+        $uargs[] = $value;
+        $pvalues[] = "'%s'";
       }
-      array_push($dargs, $value);
+      $idatatypes[] = 'text';      
     }
+    $psql .= "$field = \$" . $i . " AND ";    
+    $i++;
   }
   $sql = drupal_substr($sql, 0, -4);  // get rid of the trailing 'AND'
+  $psql = drupal_substr($psql, 0, -4);  // get rid of the trailing 'AND'
+  
+  // finish constructing the prepared SQL statement
+  $psql =  "PREPARE " . $options['statement_name'] . " (" . implode(', ', $idatatypes) . ") AS " . $psql;
 
-  // finally perform the delete.  If successful, return the updated record
-  $previous_db = tripal_db_set_active('chado');  // use chado database
-  $result = db_query($sql, $dargs);
-  tripal_db_set_active($previous_db);  // now use drupal database
-  if ($result) {
+  // finally perform the update.  If successful, return the updated record
+  if ($prepared) {
+    // if this is the first time we've run this query
+    // then we need to do the prepare, otherwise just execute
+    if ($options['is_prepared'] != TRUE and
+        !tripal_core_is_sql_prepared($options['statement_name'])) {
+      $status = chado_query($psql);
+      if (!$status) {
+        watchdog('tripal_core', "tripal_core_chado_update: not able to prepare '%name' statement for: %sql", array('%name' => $options['statement_name'], '%sql' => $sql), 'WATCHDOG ERROR');
+        return FALSE;
+      }
+    }
+    $sql = "EXECUTE " . $options['statement_name'] . "(" . implode(", ", $pvalues) . ")";
+    $resource = chado_query($sql, $ivalues);
+  }
+  // if it's not a prepared statement then insert normally
+  else {
+    $previous_db = tripal_db_set_active('chado');  // use chado database
+    $resource = db_query($sql, $uargs);
+    tripal_db_set_active($previous_db);  // now use drupal database
+  }
+  
+  if ($resource) {
     return TRUE;
   }
   else {
-    watchdog('tripal_core', "Cannot delete record in $table table.  Match:" . print_r($match, 1) . ". Values: ". print_r($values, 1), array(), 'WATCHDOG_ERROR');
+    watchdog('tripal_core', "Cannot update record in $table table.  Match:" . print_r($match, 1) . ". Values: ". print_r($values, 1), array(), 'WATCHDOG_ERROR');
     return FALSE;
   }
+
   return FALSE;
 }
-
 /**
- * Provides a generic routine for updating into any Chado table
+ * Provides a generic function for deleting a record(s) from any chado table
  *
- * Use this function to update a record in any Chado table.  The first
- * argument specifies the table for inserting, the second is an array
- * of values to matched for locating the record for updating, and the third
- * argument give the values to update.  The arrays are mutli-dimensional such
- * that foreign key lookup values can be specified.
+ * Use this function to delete a record(s) in any Chado table.  The first
+ * argument specifies the table to delete from and the second is an array
+ * of values to match for locating the record(s) to be deleted.  The arrays
+ * are mutli-dimensional such that foreign key lookup values can be specified.
  *
  * @param $table
  *  The name of the chado table for inserting
  * @param $match
  *  An associative array containing the values for locating a record to update.
- * @param $values
- *  An associative array containing the values for updating.
  *
  * @return
- *  On success this function returns TRUE. On failure, it returns FALSE.
+ *   On success this function returns TRUE. On failure, it returns FALSE.
  *
  * Example usage:
  * @code
@@ -467,18 +703,17 @@ function tripal_core_chado_delete($table, $match) {
  *   $result = tripal_core_chado_update('feature',$umatch,$uvalues);
  * @endcode
  * The above code species that a feature with a given uniquename, organism_id,
- * and type_id (the unique constraint for the feature table) will be updated.
+ * and type_id (the unique constraint for the feature table) will be deleted.
  * The organism_id is specified as a nested array that uses the organism_id
  * foreign key constraint to lookup the specified values to find the exact
  * organism_id. The same nested struture is also used for specifying the
- * values to update.  The function will find the record that matches the
- * columns specified and update the record with the avlues in the $uvalues array.
+ * values to update.  The function will find all records that match the
+ * columns specified and delete them.
  *
  * @ingroup tripal_chado_api
  */
-function tripal_core_chado_update($table, $match, $values) {
-  $update_values = array();   // contains the values to be updated
-  $update_matches = array();  // contains the values for the where clause
+function tripal_core_chado_delete($table, $match) {
+  $delete_matches = array();  // contains the values for the where clause
 
   // get the table description
   $table_desc = tripal_core_get_chado_table_schema($table);
@@ -486,90 +721,71 @@ function tripal_core_chado_update($table, $match, $values) {
   // get the values needed for matching in the SQL statement
   foreach ($match as $field => $value) {
     if (is_array($value)) {
-      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value);
-      if (sizeof($results) > 1) {
-        watchdog('tripal_core', 'tripal_core_chado_update: When trying to find record to update, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
-      }
-      elseif (sizeof($results) < 1) {
-        //watchdog('tripal_core', 'tripal_core_chado_update: When trying to find record to update, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
+      // if the user has specified an array of values to delete rather than
+      // FK relationships the keep those in our match
+      if (array_values($value) === $value) {
+        $delete_matches[$field] = $value;
       }
       else {
-        $update_matches[$field] = $results[0];
+        $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value);
+        if (sizeof($results) > 1) {
+          watchdog('tripal_core', 'tripal_core_chado_delete: When trying to find record to delete, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
+        }
+        elseif (sizeof($results) < 1) {
+          //watchdog('tripal_core', 'tripal_core_chado_delete: When trying to find record to delete, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value,TRUE)), WATCHDOG_ERROR);
+        }
+        else {
+          $delete_matches[$field] = $results[0];
+        }
       }
     }
     else {
-      $update_matches[$field] = $value;
+      $delete_matches[$field] = $value;
     }
   }
 
-  // get the values used for updating
-  foreach ($values as $field => $value) {
-    if (is_array($value)) {
-      $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value);
-      if (sizeof($results) > 1) {
-        watchdog('tripal_core', 'tripal_core_chado_update: When trying to find update values, too many records match the criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value, TRUE)), WATCHDOG_ERROR);
+  // now build the SQL statement
+  $sql = "DELETE FROM {$table} WHERE ";
+  $dargs = array();
+  foreach ($delete_matches as $field => $value) {
+    if (count($value) > 1) {
+      $sql .= "$field IN (" . db_placeholders($value, 'varchar') . ") AND ";
+      foreach ($value as $v) {
+        $dargs[] = $v;
       }
-      elseif (sizeof($results) < 1) {
-        //watchdog('tripal_core', 'tripal_core_chado_update: When trying to find update values, no record matches criteria supplied for !foreign_key foreign key constraint (!criteria)', array('!foreign_key' => $field, '!criteria' => print_r($value,TRUE)), WATCHDOG_ERROR);
+    }
+    else {
+      if (strcmp($value, '__NULL__') == 0) {
+        $sql .= " $field = NULL AND ";
+      }
+      elseif (strcmp($fields[$field]['type'], 'serial') == 0 or
+              strcmp($fields[$field]['type'], 'int') == 0) {
+        $sql .= " $field = %d AND ";
       }
       else {
-        $update_values[$field] = $results[0];
+        $sql .= " $field = '%s' AND ";
       }
+      array_push($dargs, $value);
     }
-    else {
-      $update_values[$field] = $value;
-    }
-  }
-
-  // now build the SQL statement
-  $sql = "UPDATE {$table} SET ";
-  $fields = $table_desc['fields'];
-  $uargs = array();
-  foreach ($update_values as $field => $value) {
-    if (strcmp($value, '__NULL__') == 0) {
-      $sql .= " $field = NULL, ";
-    }
-    elseif (strcmp($fields[$field]['type'], 'serial')==0 or
-      strcmp($fields[$field]['type'], 'int')==0) {
-      $sql .= " $field = %d, ";
-    }
-    else {
-      $sql .= " $field = '%s', ";
-    }
-    array_push($uargs, $value);
-  }
-  $sql = drupal_substr($sql, 0, -2);  // get rid of the trailing comma & space
-  $sql .= " WHERE ";
-  foreach ($update_matches as $field => $value) {
-    if (strcmp($value, '__NULL__')==0) {
-      $sql .= " $field = NULL AND ";
-    }
-    elseif (strcmp($fields[$field]['type'], 'serial')==0 or
-      strcmp($fields[$field]['type'], 'int')==0) {
-      $sql .= " $field = %d AND ";
-    }
-    else {
-      $sql .= " $field = '%s' AND ";
-    }
-    array_push($uargs, $value);
   }
   $sql = drupal_substr($sql, 0, -4);  // get rid of the trailing 'AND'
 
-  // finally perform the update.  If successful, return the updated record
+  // finally perform the delete.  If successful, return the updated record
   $previous_db = tripal_db_set_active('chado');  // use chado database
-  $result = db_query($sql, $uargs);
+  $result = db_query($sql, $dargs);
   tripal_db_set_active($previous_db);  // now use drupal database
   if ($result) {
     return TRUE;
   }
   else {
-    watchdog('tripal_core', "Cannot update record in $table table.  Match:" . print_r($match, 1) . ". Values: ". print_r($values, 1), array(), 'WATCHDOG_ERROR');
+    watchdog('tripal_core', "Cannot delete record in $table table.  Match:" . print_r($match, 1) . ". Values: ". print_r($values, 1), array(), 'WATCHDOG_ERROR');
     return FALSE;
   }
-
   return FALSE;
 }
 
+
+
 /**
  * Provides a generic routine for selecting data from a Chado table
  *
@@ -654,28 +870,44 @@ function tripal_core_chado_update($table, $match, $values) {
  */
 function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
 
-  // we need to get a persistent connection.  If one exists this function
-  // will not recreate it, but if not it will create one and store it in
-  // a Drupal variable for reuse later.
-  tripal_db_persistent_chado();
-
-  // get the options for this query
+  // set defaults for options. If we don't set defaults then
+  // we get memory leaks when we try to access the elements
   if (!is_array($options)) {
     $options = array();
   }
-  if (!$options['case_insensitive_columns']) {
+  if (!array_key_exists('case_insensitive_columns', $options)) {
     $options['case_insensitive_columns'] = array();
   }
-  if (!$options['regex_columns']) {
+  if (!array_key_exists('regex_columns', $options)) {
     $options['regex_columns'] = array();
   }
-  if (!$options['order_by']) {
+  if (!array_key_exists('order_by', $options)) {
     $options['order_by'] = array();
   }
-
+  if (!array_key_exists('is_prepared', $options)) {
+    $options['is_prepared'] = FALSE;
+  }
+  if (!array_key_exists('return_sql', $options)) {
+    $options['return_sql'] = FALSE;
+  }
+  if (!array_key_exists('has_record', $options)) {
+    $options['has_record'] = FALSE;
+  }
+  if (!array_key_exists('statement_name',$options)) {
+    $options['statement_name'] = FALSE;
+  }
+  
   // if this is a prepared statement check to see if it has already been prepared
   if ($options['statement_name']) {
     $prepared = TRUE;
+    // we need to get a persistent connection.  If one exists this function
+    // will not recreate it, but if not it will create one and store it in
+    // a Drupal variable for reuse later.
+    $connection = tripal_db_persistent_chado();
+  } 
+  else {
+     print "NO STATEMENT (select): $table\n";
+     debug_print_backtrace();
   }
 
   // check that our columns and values arguments are proper arrays
@@ -694,6 +926,7 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
   $from = '';
   $where = '';
   $args = array();
+
   foreach ($values as $field => $value) {
     $select[] = $field;
     if (is_array($value)) {
@@ -713,11 +946,9 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
            // add the fk relationship info to the prepared statement name so that
            // we can prepare the selects run by the recrusive tripal_core_chado_get_foreign_key
            // function.
-           $foreign_options['statement_name'] = $options['statement_name'] . "fk_" . $table . "_" . $field;
-        }
-        if ($options['prepare']) {
-           $foreign_options['prepare'] = $options['prepare'];
+           $foreign_options['statement_name'] = "fk_" . $table . "_" . $field;
         }
+
         $results = tripal_core_chado_get_foreign_key($table_desc, $field, $value, $foreign_options);
         if (!$results or count($results) ==0) {
 
@@ -807,6 +1038,14 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
           $idatatypes[] = 'bool';
           $pvalues[] = $value[0];
         }
+        elseif (strcasecmp($table_desc['fields'][$field]['type'], 'float')==0) {
+          $sql .= "$field $operator %s AND ";
+          $psql .= "$field $operator \$" . $i . " AND ";
+          $args[] = $value[0];
+          // set the variables needed for the prepared statement
+          $idatatypes[] = 'numeric';
+          $pvalues[] = $value[0];
+        }
         // else the type is a text
         else {
           if (in_array($field, $options['case_insensitive_columns'])) {
@@ -848,7 +1087,7 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
 
   // if the caller has requested the SQL rather than the results...
   // which happens in the case of wanting to use the Drupal pager, then do so
-  if ($options['return_sql']) {
+  if ($options['return_sql'] == TRUE) {
     return array('sql' => $sql, 'args' => $args);
   }
 
@@ -859,16 +1098,16 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
     if ($options['is_prepared'] != TRUE and
         !tripal_core_is_sql_prepared($options['statement_name'])) {
       $status = chado_query($psql);
-#      print "$psql\n";
       if (!$status) {
         watchdog('tripal_core', "tripal_core_chado_select: not able to prepare '%name' statement for: %sql", array('%name' => $options['statement_name'], '%sql' => $sql), 'WATCHDOG ERROR');
         return FALSE;
       }
     }
     $sql = "EXECUTE " . $options['statement_name'] . "(" . implode(", ", $pvalues) . ")";
-#    print "$sql\n";
+    // WARNING: This call creates a memory leak:  if you remove the $ivalues it doesn't
+    // do this. Got to find out what's causing this.
     $resource = chado_query($sql, $ivalues);
-  }
+  }  
   else {
     $previous_db = tripal_db_set_active('chado');  // use chado database
     $resource = db_query($sql, $args);
@@ -880,12 +1119,10 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
   while ($r = db_fetch_object($resource)) {
     $results[] = $r;
   }
+
   if ($options['has_record']) {
     return count($results);
   }
-#  print "$psql\n";
-#  print "$sql\n";
-#  print '$results = ' . print_r($results, 1);
   return $results;
 }
 
@@ -938,16 +1175,19 @@ function tripal_core_chado_select($table, $columns, $values, $options = NULL) {
  * @ingroup tripal_chado_api
  */
 function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $options = NULL) {
-
+ 
+  // set defaults for options. If we don't set defaults then
+  // we get memory leaks when we try to access the elements
   if (!is_array($options)) {
     $options = array();
   }
-  if (!$options['case_insensitive_columns']) {
+  if (!array_key_exists('case_insensitive_columns', $options)) {
     $options['case_insensitive_columns'] = array();
   }
-  if (!$options['regex_columns']) {
+  if (!array_key_exists('regex_columns', $options)) {
     $options['regex_columns'] = array();
   }
+  
 
   // get the list of foreign keys for this table description and
   // iterate through those until we find the one we're looking for
@@ -1540,17 +1780,18 @@ function tripal_core_exclude_field_from_feature_by_default() {
 function chado_query($sql) {
 
   $args = func_get_args();
-  array_shift($args);
+  array_shift($args); // remove the $sql from the argument list
   $sql = db_prefix_tables($sql);
   if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
     $args = $args[0];
   }
+
   _db_query_callback($args, TRUE);
   $sql = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $sql);
 
   // Execute the query on the chado database/schema
   // Use the persistent chado connection if it already exists
-  $persistent_connection = variable_get('tripal_perisistent_chado', NULL);
+  $persistent_connection = unserialize(variable_get('tripal_perisistent_chado', NULL));
   if ($persistent_connection) {
 
     $query = $sql;
@@ -2034,12 +2275,32 @@ function tripal_db_set_active($dbname) {
  *   TRUE if the statement is preapred, FALSE otherwise
  */
 function tripal_core_is_sql_prepared($statement_name) {
+
+  // to reduce the need for a database query we will check the
+  // session variable for this connection to see if the statement
+  // has been prepared. If it has then we won't do the database
+  // query to find out.  If it hasn't then we'll query the database
+  // to see if it is prepared.
+  $connection = variable_get('tripal_perisistent_chado', NULL);
+  if (!isset($_SESSION[$connection])) {
+    $_SESSION[$connection] = array();
+  }
+  if(in_array($statement_name,$_SESSION[$connection])){
+     //print "Is Prepared and in Session var: $statement_name\n";
+     return TRUE;
+  } 
+
   // @coder-ignore: acting on postgres tables rather then drupal schema therefore, table prefixing does not apply
   $sql = "SELECT name FROM pg_prepared_statements WHERE name = '%s'";
-  $result = db_fetch_object(chado_query($sql, $statement_name));
+  // do not use 'chado_query' here or it causes memory-leaks
+  $result = db_fetch_object(db_query($sql, $statement_name));
+
   if ($result) {
+     $_SESSION[$connection][] = $statement_name;
+     //print "Is Prepared but in DB: $statement_name\n";
      return TRUE;
   }
+  //print "Is Not prepared: $statement_name\n";
   return FALSE;
 }
 /**
@@ -2055,12 +2316,11 @@ function tripal_db_persistent_chado() {
   global $db_url;
 
   // get connection if it already exists
-  $connection = variable_get('tripal_perisistent_chado', NULL);
+  // Otherwise we need to set it
+  $connection = unserialize(variable_get('tripal_perisistent_chado', NULL));
 
   if ($connection) {
     return $connection;
-
-  // Otherwise we need to set it
   }
   else {
     if (is_array($db_url) && isset($db_url['chado'])) {
@@ -2069,9 +2329,8 @@ function tripal_db_persistent_chado() {
     }
     else {
       $connection = db_connect($db_url);
-      variable_set('tripal_perisistent_chado', $connection);
-    }
-
+      variable_set('tripal_perisistent_chado', serialize($connection));
+    }    
     return $connection;
   }
   return FALSE;
@@ -2089,7 +2348,7 @@ function tripal_db_release_persistent_chado() {
  */
 function tripal_db_start_transaction() {
   $connection = tripal_db_persistent_chado();
-  chado_query("BEGIN");
+  chado_query("BEGIN");  
 }
 
 /**

File diff suppressed because it is too large
+ 360 - 205
tripal_feature/includes/gff_loader.inc


Some files were not shown because too many files changed in this diff