浏览代码

Fixed memory leaks in the Tripal core API when storing the persistent connection. Alos fixed memory leaks in GFF loader and added loading of FASTA sequences embeded in the GFF file ##FASTA section

spficklin 12 年之前
父节点
当前提交
09b02611ed

+ 52 - 64
tripal_core/api/tripal_core.api.inc

@@ -2217,6 +2217,7 @@ function tripal_core_exclude_field_from_feature_by_default() {
  *   executed correctly
  */
 function chado_query($sql) {
+  global $persistent_chado;
 
   $is_local = tripal_core_is_chado_local();
 
@@ -2249,13 +2250,12 @@ function chado_query($sql) {
 
   // Execute the query on the chado database/schema
   // Use the persistent chado connection if it already exists
-  $persistent_connection = variable_get('tripal_persistent_chado', NULL);
-  if ($persistent_connection) {
+  if ($persistent_chado) {
 
     $query = $sql;
     // Duplicate the _db_query code in order to ensure that the drupal
     // $active_db variable is not used in the pg_query command
-    // thus changed $active_db to $persistent_connection
+    // thus changed $active_db to $persistent_chado
     // START COPY FROM _db_query in database.pgsql.inc
     if (variable_get('dev_query', 0)) {
       list($usec, $sec) = explode(' ', microtime());
@@ -2263,11 +2263,11 @@ function chado_query($sql) {
     }
     // if we're local we can just run the query
     if ($is_local) {
-      $last_result = pg_query($persistent_connection, $query);
+      $last_result = pg_query($persistent_chado, $query);
     }
     else {
       $previous_db = tripal_db_set_active('chado');
-      $last_result = pg_query($persistent_connection, $query);
+      $last_result = pg_query($persistent_chado, $query);
       tripal_db_set_active($previous_db);
     }
 
@@ -2286,7 +2286,7 @@ function chado_query($sql) {
     else {
       // Indicate to drupal_error_handler that this is a database error.
       ${DB_ERROR} = TRUE;
-      trigger_error(check_plain(pg_last_error($persistent_connection) . "\nquery: " . $query), E_USER_WARNING);
+      trigger_error(check_plain(pg_last_error($persistent_chado) . "\nquery: " . $query), E_USER_WARNING);
       return FALSE;
     }
     // END COPY FROM _db_query in database.pgsql.inc
@@ -2810,32 +2810,21 @@ function tripal_db_set_default_search_path() {
  *   TRUE if the statement is preapred, FALSE otherwise
  */
 function tripal_core_is_sql_prepared($statement_name) {
+  global $prepared_statements;
 
-  // 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_persistent_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";
+  // check to see if the statement is prepared already  
+  if (in_array($statement_name, $prepared_statements)) {
     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'";
   // 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";
+  if ($result) {    
     return TRUE;
   }
-  //print "Is Not prepared: $statement_name\n";
   return FALSE;
 }
 
@@ -2853,9 +2842,10 @@ function tripal_core_is_sql_prepared($statement_name) {
  *   be the type of value needed (ie: text, int, etc.)
  */
 function tripal_core_chado_prepare($statement_name, $psql, $args) {
-  $connection = variable_get('tripal_persistent_chado', NULL);
-
-  if (!$connection) {
+  global $persistent_chado;
+  global $prepared_statements;
+  
+  if (!$persistent_chado) {
     watchdog('tripal_core', "chado_prepare: not able to prepare '%name' statement as no persistent connection is available", array('%name' => $statement_name, '%sql' => $psql), WATCHDOG_ERROR);
     return FALSE;
   }
@@ -2863,15 +2853,16 @@ function tripal_core_chado_prepare($statement_name, $psql, $args) {
   // Check to see if this statement was already prepared
   if (tripal_core_is_sql_prepared($statement_name)) {
     // check that the arguments are the same
-    $prepared_args = $_SESSION['prepared_args'][$connection][$statement_name];
-    $prepared_sql = $_SESSION['prepared_sql'][$connection][$statement_name];
+    $prepared_args = $prepared_statements[$statement_name]['prepared_args'];
+    $prepared_sql = $prepared_statements[$statement_name]['prepared_sql'];
     if ($prepared_args == $args) {
       // This statement is already prepared
       return TRUE;
     }
     else {
       // Although a statement with this name is already prepared it is not the same!
-      watchdog('tripal_core', "chado_prepare: '%name' statement already prepared with different arguments! You want to prepare %sql with %values and the existing statement is %esql with %existing",
+      watchdog('tripal_core', "chado_prepare: '%name' statement already prepared with different arguments! ". 
+        "You want to prepare \n%sql\n with \n%values\n and the existing statement is \n%esql\n with \n%existing",
         array('%name' => $statement_name, '%sql' => $psql, '%values' => print_r($args, TRUE), '%esql' => $prepared_sql,
           '%existing' => print_r($prepared_args, TRUE)), WATCHDOG_ERROR);
       return FALSE;
@@ -2884,10 +2875,9 @@ function tripal_core_chado_prepare($statement_name, $psql, $args) {
     return FALSE;
   }
   else {
-    //watchdog('tripal_core', "tripal_core_chado_select: prepared '%name' statement as %sql", array('%name' => $statement_name, '%sql' => $psql), WATCHDOG_NOTICE);
-    $_SESSION[$connection][] = $statement_name;
-    $_SESSION['prepared_args'][$connection][$statement_name] = $args;
-    $_SESSION['prepared_sql'][$connection][$statement_name] = $psql;
+    $prepared_statements[$statement_name] = array();
+    $prepared_statements[$statement_name]['prepared_args'] = $args;
+    $prepared_statements[$statement_name]['prepared_sql'] = $psql;
     return TRUE;
   }
 }
@@ -2904,7 +2894,7 @@ function tripal_core_chado_prepare($statement_name, $psql, $args) {
  *   An array of values in the execute sql statement
  */
 function tripal_core_chado_execute_prepared($statement_name, $sql, $values) {
-  $connection = variable_get('tripal_persistent_chado', NULL);
+  global $prepared_statements;   
 
   if (!tripal_core_is_sql_prepared($statement_name)) {
     watchdog('tripal_core', "tripal_core_chado_execute_prepared: Cannot execute an unprepared statement: '%name'", array('%name' => $statement_name), WATCHDOG_ERROR);
@@ -2912,7 +2902,7 @@ function tripal_core_chado_execute_prepared($statement_name, $sql, $values) {
   }
 
   // Before Executing, Ensure that all the values are supplied
-  $required_values = $_SESSION['prepared_args'][$connection][$statement_name];
+  $required_values = $prepared_statements[$statement_name]['prepared_args'];
   if (!$required_values) {
     watchdog('tripal_core', "tripal_core_chado_execute_prepared: missing prepare arguments for this statement: '%name'", array('%name' => $statement_name), WATCHDOG_ERROR);
     return FALSE;
@@ -2928,30 +2918,30 @@ function tripal_core_chado_execute_prepared($statement_name, $sql, $values) {
             $check = is_string($v);
             if ($v != '' and !$check) {
               watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement, field %k. Expected %required but recieved '%value'",
-                array('%name' => $statement_name, '%k' => $k, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
+                array('%name' => $statement_name, '%k' => $k+1, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
               return FALSE;
             }
             break;
           case 'int':
             $check = is_numeric($v);
             if (!$check) {
-              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement. Expected %required but recieved '%value'",
-                array('%name' => $statement_name, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
+              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement, field %k. Expected %required but recieved '%value'",
+                array('%name' => $statement_name, '%k' => $k+1, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
               return FALSE;
             }
             break;
           case 'bool':
             if ($v != 'TRUE' and $v != 'FALSE') {
-              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement. Expected %required but recieved '%value'",
-                array('%name' => $statement_name, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
+              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement, field %k. Expected %required but recieved '%value'",
+                array('%name' => $statement_name, '%k' => $k+1, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
               return FALSE;
             }
             break;
           case 'numeric':
             $check = is_numeric($v);
             if (!$check) {
-              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement. Expected %required but recieved '%value'",
-                array('%name' => $statement_name, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
+              watchdog('tripal_core', "chado_execute_prepared: wrong argument type supplied for '%name' statement, field %k. Expected %required but recieved '%value'",
+                array('%name' => $statement_name, '%k' => $k+1, '%required' => $required_values[$k], '%value' => print_r($v, TRUE)), WATCHDOG_ERROR);
               return FALSE;
             }
             break;
@@ -2974,8 +2964,10 @@ function tripal_core_chado_execute_prepared($statement_name, $sql, $values) {
     return $resource;
   }
   else {
-    watchdog('tripal_core', "chado_execute_prepared: wrong number of arguments supplied for '%name' statement. Expected %required but recieved %values. Statement: %statement.",
-      array('%name' => $statement_name, '%required' => print_r($required_values, TRUE), '%values' => print_r($values, TRUE), '%statement' => $_SESSION['prepared_sql'][$connection][$statement_name]), WATCHDOG_ERROR);
+    watchdog('tripal_core', "chado_execute_prepared: wrong number of arguments supplied for '%name' statement. ' .
+      'Expected %required but recieved %values. Statement: %statement.",
+      array('%name' => $statement_name, '%required' => print_r($required_values, TRUE), 
+        '%values' => print_r($values, TRUE), '%statement' => $prepared_statements[$statement_name]['prepared_sql']), WATCHDOG_ERROR);
     return FALSE;
   }
 }
@@ -2987,29 +2979,25 @@ function tripal_core_chado_execute_prepared($statement_name, $sql, $values) {
  * Otherwise, it clears prepared statement names that match the regex provided
  */
 function tripal_core_chado_clear_prepared ($statement_name_regex = NULL) {
-
-  $connection = variable_get('tripal_persistent_chado', NULL);
-
+  global $prepared_statements;   
+  
   if ($statement_name_regex) {
     $resource = chado_query("SELECT * FROM pg_catalog.pg_prepared_statements WHERE name~'%s'",$statement_name_regex);
     while ($r = db_fetch_object($resource)) {
-      $k = array_search($r->name,$_SESSION[$connection]);
-      unset($_SESSION[$connection][$k]);
-      unset($_SESSION['prepared_sql'][$connection][$r->name]);
-      unset($_SESSION['prepared_args'][$connection][$r->name]);
+      $k = array_search($r->name, $prepared_statements);
+      unset($prepared_statements[$k]);
       chado_query('DEALLOCATE PREPARE %s',$r->name);
     }
   }
   else {
-    unset($_SESSION['prepared_args'][$connection]);
-    unset($_SESSION['prepared_sql'][$connection]);
-    unset($_SESSION[$connection]);
+    $prepared_statements = array();
     chado_query('DEALLOCATE PREPARE ALL');
   }
 }
 
 /**
- * Instantiate or Return a persistent chado connection
+ * Instantiate or Return a persistent chado connection.  This should not be confused with
+ * PHP persistent connections. Here we use the drupal db_connect function to 
  *
  * NOTE: cannot use $active_db since a new connection is created each time
  * db_set_active() is called
@@ -3019,12 +3007,11 @@ function tripal_core_chado_clear_prepared ($statement_name_regex = NULL) {
  */
 function tripal_db_persistent_chado() {
   global $db_url;
+  global $persistent_chado;
 
-  // get connection if it already exists
-  // Otherwise we need to set it
-  $sconn = variable_get('tripal_persistent_chado', NULL);
-  if ($sconn) {
-    return $sconn;
+  // get connection if it already exists otherwise we need to set it
+  if ($persistent_chado) {
+    return $persistent_chado;
   }
   else {
     if (is_array($db_url) && isset($db_url['chado'])) {
@@ -3033,7 +3020,7 @@ function tripal_db_persistent_chado() {
         watchdog('tripal_core', "Could not create persistant connection", array(), WATCHDOG_ERROR);
         return FALSE;
       }
-      variable_set('tripal_persistent_chado', $connection);
+      $persistent_chado = $connection;
     }
     else {
       if (is_array($db_url)) {
@@ -3043,11 +3030,11 @@ function tripal_db_persistent_chado() {
         $connection = db_connect($db_url);
       }
       if (!$connection) {
-        variable_set('tripal_persistent_chado', NULL);
+        $persistent_chado = NULL;
         watchdog('tripal_core', "Could not create persistant connection", array(), WATCHDOG_ERROR);
         return FALSE;
       }
-      variable_set('tripal_persistent_chado', $connection);
+      $persistent_chado = $connection;
     }
     return $connection;
   }
@@ -3058,7 +3045,7 @@ function tripal_db_persistent_chado() {
  * Release a persistent chado connection
  */
 function tripal_db_release_persistent_chado() {
-  variable_del('tripal_persistent_chado');
+  $persistent_chado = NULL;
 }
 
 /**
@@ -3567,7 +3554,8 @@ function tripal_core_is_chado_installed() {
 function tripal_core_is_chado_local() {
   global $db_url, $db_type;
 
-  if (tripal_core_is_chado_installed) {
+  $is_installed = tripal_core_is_chado_installed();
+  if ($is_installed) {
     if (is_array($db_url)) {
       if (isset($db_url['chado'])) {
         return FALSE;

+ 7 - 0
tripal_core/tripal_core.module

@@ -26,6 +26,13 @@ require_once "api/tripal_core.ahah.inc";
 function tripal_core_init() {
   global $base_url;  
   
+  // we need to declare here the persistent_chado global variable
+  global $persistent_chado;
+  global $prepared_statements;
+  $persistent_chado = NULL;
+  $prepared_statements = array();
+  
+  
   drupal_add_js(drupal_get_path('theme', 'tripal') . '/js/tripal.ahah.js');
   
   // create the 'tripal' controlled volcabulary in chado but only if it doesn't already exist, and

+ 1 - 1
tripal_cv/api/tripal_cv.api.inc

@@ -413,7 +413,7 @@ function tripal_cv_add_cvterm($term, $defaultcv = '_global', $is_relationship =
         INNER JOIN db DB on DBX.db_id = DB.db_id
         INNER JOIN cv CV on CV.cv_id = CVT.cv_id
       WHERE DBX.accession = $1 and DB.name = $2";
-    if (!chado_query($pcvtermsql)) {
+    if (!tripal_core_chado_prepare('sel_cvterm_by_accession', $pcvtermsql, array('text', 'text'))) {
       watchdog('tripal_cv', "Cannot prepare statement 'sel_cvterm_by_accession'", NULL, WATCHDOG_WARNING);
       return 0; 
     }

+ 3 - 3
tripal_feature/api/tripal_feature.api.inc

@@ -650,7 +650,7 @@ function tripal_feature_get_formatted_sequence($feature_id, $feature_name,
                 INNER JOIN cvterm OCVT on OF.type_id = OCVT.cvterm_id
               WHERE SF.feature_id = $3) as tbl1
     ';              
-    $status = chado_query($psql);
+    $status = tripal_core_chado_prepare('sequence_by_parent', $psql, array('int', 'int', 'int'));
     if (!$status) {
       watchdog('tripal_views_handler_field_sequence', 
         "init: not able to prepare SQL statement '%name'", 
@@ -669,7 +669,7 @@ function tripal_feature_get_formatted_sequence($feature_id, $feature_name,
               INNER JOIN feature PF on PF.feature_id = FL.srcfeature_id
             WHERE FR.object_id = $1 and PF.feature_id = $2
             ORDER BY FL.fmin ASC';            
-    $status = chado_query($psql);
+    $status = tripal_core_chado_prepare('sub_features', $psql, array('int', 'int'));
     if (!$status) {
       watchdog('tripal_views_handler_field_sequence', 
         "init: not able to prepare SQL statement '%name'", 
@@ -683,7 +683,7 @@ function tripal_feature_get_formatted_sequence($feature_id, $feature_name,
               INNER JOIN featureloc FL on FL.feature_id = FR.subject_id
               INNER JOIN feature PF on PF.feature_id = FL.srcfeature_id
             WHERE FR.object_id = $1 and PF.feature_id = $2';            
-    $status = chado_query($psql);
+    $status = tripal_core_chado_prepare('count_sub_features', $psql, array('int', 'int'));
     if (!$status) {
       watchdog('tripal_views_handler_field_sequence', 
         "init: not able to prepare SQL statement '%name'", 

+ 133 - 52
tripal_feature/includes/gff_loader.inc

@@ -231,10 +231,16 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
   // empty the temp table
   $sql = "DELETE FROM tripal_gff_temp";
   chado_query($sql);
-    
+
+  // get a persistent connection
+  $connection = tripal_db_persistent_chado();
+  if (!$connection) {
+     print "A persistant connection was not obtained. Loading will be slow\n";
+  }
+  
   // begin the transaction
   if ($use_transaction) {
-    $connection = tripal_db_start_transaction();
+    tripal_db_start_transaction();
         
     // if we cannot get a connection then let the user know the loading will be slow
     if (!$connection) {
@@ -246,12 +252,6 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
              "insertions/updates is rolled back and will not be found in the database\n\n";
     }
   }
-  else {
-    $connection = tripal_db_persistent_chado();
-    if (!$connection) {
-       print "A persistant connection was not obtained. Loading will be slow\n";
-    }
-  }
 
   // check to see if the file is located local to Drupal
   $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $gff_file;
@@ -301,6 +301,25 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
   $line_num = 0;
   $num_read = 0;
   $intv_read = 0;
+  
+  // prepare the statement used to get the cvterm for each feature.
+  if (!tripal_core_is_sql_prepared('sel_cvterm_idnasy')) {
+    $psql = "PREPARE sel_cvterm_idnasy (int, text, text) AS
+             SELECT CVT.cvterm_id, CVT.cv_id, CVT.name, CVT.definition,
+                CVT.dbxref_id, CVT.is_obsolete, CVT.is_relationshiptype
+             FROM {cvterm} CVT
+                INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
+                LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
+             WHERE CV.cv_id = $1 and 
+               (lower(CVT.name) = lower($2) or lower(CVTS.synonym) = lower($3))";
+     $status = tripal_core_chado_prepare('sel_cvterm_idnasy', $psql, array('int','text','text'));
+     if (!$status) {
+       watchdog('T_gff3_loader', 'cannot prepare statement \'sel_cvterm_idnasy\'.', 
+         array(), WATCHDOG_ERROR);
+       return '';
+       
+     }  
+  } 
 
   // iterate through each line of the GFF file
   print "Parsing Line $line_num (0.00%). Memory: " . number_format(memory_get_usage()) . " bytes\r";
@@ -321,8 +340,8 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
     // check to see if we have FASTA section, if so then set the variable
     // to start parsing
     if (preg_match('/^##FASTA/i', $line)) {
-      $in_fasta = 1;
-      break;
+      tripal_feature_load_gff_fasta($fh, $interval, $num_read, $intv_read, $line_num);
+      continue;
     }
     
     // skip comments
@@ -333,9 +352,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
     // skip empty lines
     if (preg_match('/^\s*$/', $line)) {
       continue;
-    }
-    
-    // TODO: handle FASTA section
+    }    
 
     // get the columns
     $cols = explode("\t", $line);
@@ -378,35 +395,16 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
     if (strcmp($phase, '.') == 0) {
       $phase = '';
     }
-
-    // get the type record
-    if (!tripal_core_is_sql_prepared('sel_cvterm_idnasy')) {
-      $psql = "PREPARE sel_cvterm_idnasy (int, text, text) AS
-               SELECT CVT.cvterm_id, CVT.cv_id, CVT.name, CVT.definition,
-                  CVT.dbxref_id, CVT.is_obsolete, CVT.is_relationshiptype
-               FROM {cvterm} CVT
-                  INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
-                  LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
-               WHERE CV.cv_id = $1 and (CVT.name = $2 or CVTS.synonym = $3)";
-       $status = chado_query($psql);
-       if (!$status) {
-         watchdog('T_gff3_loader', 'cannot prepare statement \'sel_cvterm_idnasy\' for ontology term %line_num', 
-           array('%line_num' => $line_num), WATCHDOG_ERROR);
-         return '';
-      }
-      
-    } 
   
     $result = chado_query("EXECUTE sel_cvterm_idnasy (%d, '%s', '%s')", $cv->cv_id, $type, $type);
-   
+
     $cvterm = db_fetch_object($result);
     if (!$cvterm) {
-      watchdog('T_gff3_loader', 'cannot find ontology term \'%type\' on line %line_num', 
+      watchdog('T_gff3_loader', 'cannot find feature term \'%type\' on line %line_num of the GFF file', 
         array('%type' => $type, '%line_num' => $line_num), WATCHDOG_ERROR);
       return '';
     }
- 
-
+     
     // break apart each of the attributes
     $tags = array();
     $attr_name = '';
@@ -419,6 +417,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
     $attr_is_analysis = 'f';
     $attr_others = '';
     $residues = '';
+    
     foreach ($attrs as $attr) {
       $attr = rtrim($attr);
       $attr = ltrim($attr);
@@ -501,8 +500,9 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
          'uniquename'  => $landmark,
       );
       $columns = array('count(*) as num_landmarks');
-      $options = array('statement_name' => 'sel_feature_organismid_uniquename');
+      $options = array('statement_name' => 'sel_feature_numland');      
       $count = tripal_core_chado_select('feature', $columns, $select, $options);
+     
       if (!$count or $count[0]->num_landmarks == 0) {
         watchdog('T_gff3_loader', "The landmark '%landmark' cannot be found for this organism. ".
               "Please add the landmark and then retry the import of this GFF3 ".
@@ -574,7 +574,6 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
             $landmark, $fmin, $fmax, $strand, $phase, $attr_fmin_partial,
             $attr_fmax_partial, $attr_residue_info, $attr_locgroup);
         }
-
         // add any aliases for this feature
         if (array_key_exists('Alias', $tags)) {
           tripal_feature_load_gff3_alias($feature, $tags['Alias']);
@@ -636,8 +635,6 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
               array('%target' => $tags['Target'][0]), WATCHDOG_ERROR);            
           }
         }
-        
-        
         // add gap information.  This goes in simply as a property
         if (array_key_exists('Gap', $tags)) {
           foreach ($tags['Gap'] as $value) {
@@ -650,6 +647,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
               tripal_feature_load_gff3_property($feature, 'Note', $value);
           }
         }
+
         // add the Derives_from relationship (e.g. polycistronic genes).
         if (array_key_exists('Derives_from', $tags)) {
           tripal_feature_load_gff3_derives_from($feature, $tags['Derives_from'][0], $organism);
@@ -667,6 +665,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
             }
           }
         }
+        
       }
     }
   }
@@ -696,7 +695,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
     $sql = "PREPARE sel_gffchildren (int) AS " . $sql . " WHERE FR.object_id = \$1 ORDER BY FL.fmin ASC";            
   }
   if (!tripal_core_is_sql_prepared('sel_gffchildren')) {
-    $success = chado_query($sql);
+    $success = tripal_core_chado_prepare('sel_gffchildren', $sql, array('int'));
     if (!$success) {
       watchdog("T_gff3_loader", "Cannot prepare statement 'sel_gffchildren' and cannot set children ranks.", 
          array(), WATCHDOG_WARNING);
@@ -846,7 +845,7 @@ function tripal_feature_load_gff3_parents($feature, $cvterm, $parents, $organism
                INNER JOIN cv CV on CVT.cv_id = CV.cv_id
                LEFT JOIN cvtermsynonym CVTS on CVTS.cvterm_id = CVT.cvterm_id
              WHERE cv.name = $1 and (CVT.name = $2 or CVTS.synonym = $3)";
-    $status = chado_query($psql);
+    $status = tripal_core_chado_prepare('sel_cvterm_cvname_cvtname_synonym', $psql, array('text', 'text' ,'text'));
     if (!$status) {
        watchdog("T_gff3_loader", "Cannot prepare statement 'sel_cvterm_cvname_cvtname_synonym' for ontology term", 
          array(), WATCHDOG_WARNING);
@@ -1204,7 +1203,7 @@ function tripal_feature_load_gff3_alias($feature, $aliases) {
                     INNER JOIN dbxref DBX on DBX.dbxref_id = CVT.dbxref_id
                     INNER JOIN db DB on DB.db_id = DBX.db_id
                   WHERE CVT.name = $1 and DB.name = $2)";
-        $status = chado_query($psql);
+        $status = tripal_core_chado_prepare('ins_pub_uniquename_typeid', $psql, args('text', 'text'));
         if (!$status) {
           watchdog("T_gff3_loader", "Cannot prepare statement 'ins_pub_uniquename_typeid", array(), WATCHDOG_WARNING);
           return 0;
@@ -1393,9 +1392,9 @@ function tripal_feature_load_gff3_featureloc($feature, $organism, $landmark, $fm
     'uniquename' => $landmark,
   );
   $options = array('statement_name' => 'sel_feature_orun');  
-  $r = tripal_core_chado_select('feature', array('feature_id'), $select, $options);
+  $results = tripal_core_chado_select('feature', array('feature_id'), $select, $options);
   
-  if (count($r)==0) {
+  if (count($results)==0) {
     // so we couldn't find the landmark using the uniquename. Let's try the 'name'.
     // if we return only a singe result then we can proceed. Otherwise give an
     // error message
@@ -1403,19 +1402,19 @@ function tripal_feature_load_gff3_featureloc($feature, $organism, $landmark, $fm
       'organism_id' => $organism->organism_id,
       'name' => $landmark,
     );
-    $options = array('statement_name' => 'sel_feature_organism_id_name');
-    $r = tripal_core_chado_select('feature', array('feature_id'), $select, $options);
-    if (count($r) == 0) {
+    $options = array('statement_name' => 'sel_feature_orna');
+    $results = tripal_core_chado_select('feature', array('feature_id'), $select, $options);
+    if (count($results) == 0) {
        watchdog("T_gff3_loader", "Cannot find landmark feature: '$landmark'.", array(), WATCHDOG_WARNING);
        return 0;
     } 
-    elseif (count($r) > 1) {
+    elseif (count($results) > 1) {
        watchdog("T_gff3_loader", "multiple landmarks exist with the name: '$landmark'.  Cannot resolve which one to use. Cannot add the feature location record", 
          array(), WATCHDOG_WARNING);
        return 0;    
     }    
   }
-  $srcfeature = $r[0];
+  $srcfeature = $results[0];
 
   // TODO: create an attribute that recognizes the residue_info,locgroup, 
   //  is_fmin_partial and is_fmax_partial, right now these are
@@ -1495,8 +1494,7 @@ function tripal_feature_load_gff3_featureloc($feature, $organism, $landmark, $fm
     if ($phase) {
       $values['phase'] = $phase;
       $options = array('statement_name' => 'ins_featureloc_allphase');
-    }
-    
+    }    
     $success = tripal_core_chado_insert('featureloc', $values, $options);
     if (!$success) {
       watchdog("T_gff3_loader", "Failed to insert featureloc", array(), WATCHDOG_WARNING);
@@ -1522,7 +1520,9 @@ function tripal_feature_load_gff3_property($feature, $property, $value) {
   );
   $options = array('statement_name' => 'sel_cvterm_name_cvid');
   $result = tripal_core_chado_select('cvterm', array('*'), $select, $options);
-  if (count($cvterm) == 0) {
+
+  // if we don't have a property like this already, then add it otherwise, just return
+  if (count($result) == 0) {
     $term = array(
       'id' => "null:$property",
       'name' => $property,
@@ -1579,3 +1579,84 @@ function tripal_feature_load_gff3_property($feature, $property, $value) {
   }
 }
 
+/*
+ * 
+ */
+function tripal_feature_load_gff_fasta($fh, $interval, &$num_read, &$intv_read, &$line_num) {
+  print "Loading FASTA sequences\n";
+  $residues = '';
+  $sql = " 
+    PREPARE sel_gfftemp_un (text) AS
+    SELECT feature_id FROM tripal_gff_temp
+    WHERE uniquename = $1
+  ";
+  $status = tripal_core_chado_prepare('sel_gfftemp_un', $sql, array('text'));
+  if (!$status) {
+   watchdog('T_gff3_loader', 'Cannot prepare statement \'sel_gfftemp_un\'.', 
+     array(), WATCHDOG_ERROR);
+   return '';  
+  }
+  $id = NULL;
+  
+  // iterate through the remainig lines of the file
+  while ($line = fgets($fh)) {
+    
+    $line_num++;
+    $num_read += drupal_strlen($line);   
+    $intv_read += $num_read; 
+    $line = trim($line);      
+
+    // update the job status every 1% features
+    if ($job and $intv_read >= $interval) {
+      $intv_read = 0;
+      $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
+      print "Parsing Line $line_num (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
+      tripal_job_set_progress($job, intval(($num_read / $filesize) * 100));
+    }
+    
+    // if we encounter a definition line then get the name, uniquename,
+    // accession and relationship subject from the definition line
+    if (preg_match('/^>/', $line)) {   
+      // if we are beginning a new sequence then save the last one we 
+      // just finished.     
+             
+      if ($id) {
+        $sql = "EXECUTE sel_gfftemp_un('%s')";
+        $result = tripal_core_chado_execute_prepared('sel_gfftemp_un', $sql, array($id));
+        if (!$result) {
+          watchdog('T_gff3_loader', 'Cannot find feature to assign FASTA sequence: %uname', 
+             array('%uname' => $id), WATCHDOG_WARNING); 
+        }
+        // if we have a feature then add the residues
+        else {    
+          $feature = db_fetch_object($result);    
+          $values = array('residues' => $residues);
+          $match = array('feature_id' => $feature->feature_id);
+          $options = array('statement_name' => 'upd_feature_re');
+          tripal_core_chado_update('feature', $match, $values, $options);
+        }
+      }
+      // get the feature ID for this ID from the tripal_gff_temp table
+      $id = preg_replace('/^>(.*)$/', '\1', $line);      
+      $residues = '';
+    }
+    else {
+      $residues .= trim($line);
+    }
+  } 
+  // add in the last sequence
+  $sql = "EXECUTE sel_gfftemp_un('%s')";
+  $result = tripal_core_chado_execute_prepared('sel_gfftemp_un', $sql, array($id));
+  if (!$result) {
+    watchdog('T_gff3_loader', 'Cannot find feature to assign FASTA sequence: %uname', 
+       array('%uname' => $id), WATCHDOG_WARNING); 
+  }
+  // if we have a feature then add the residues
+  else {        
+    $feature = db_fetch_object($result);    
+    $values = array('residues' => $residues);
+    $match = array('feature_id' => $feature->feature_id);
+    $options = array('statement_name' => 'upd_feature_re');
+    tripal_core_chado_update('feature', $match, $values, $options);
+  } 
+}