فهرست منبع

Fixed bug where featurelocs weren't showing up if one of the two FK relationships returned NULL

spficklin 12 سال پیش
والد
کامیت
a52dc176d2
2فایلهای تغییر یافته به همراه177 افزوده شده و 138 حذف شده
  1. 83 40
      tripal_core/api/tripal_core.api.inc
  2. 94 98
      tripal_feature/tripal_feature.module

+ 83 - 40
tripal_core/api/tripal_core.api.inc

@@ -391,28 +391,28 @@ function tripal_core_chado_insert($table, $values, $options = array()) {
  * Example usage:
  * @code
  $umatch = array(
- 'organism_id' => array(
- 'genus' => 'Citrus',
- 'species' => 'sinensis',
- ),
- 'uniquename' => 'orange1.1g000034m.g7',
- 'type_id' => array (
- 'cv_id' => array (
- 'name' => 'sequence',
- ),
- 'name' => 'gene',
- 'is_obsolete' => 0
- ),
+   'organism_id' => array(
+     'genus' => 'Citrus',
+     'species' => 'sinensis',
+   ),
+   'uniquename' => 'orange1.1g000034m.g7',
+   'type_id' => array (
+     'cv_id' => array (
+       'name' => 'sequence',
+     ),
+     'name' => 'gene',
+     'is_obsolete' => 0
+   ),
  );
  $uvalues = array(
- 'name' => 'orange1.1g000034m.g',
- 'type_id' => array (
- 'cv_id' => array (
- 'name' => 'sequence',
- ),
- 'name' => 'mRNA',
- 'is_obsolete' => 0
- ),
+   'name' => 'orange1.1g000034m.g',
+   'type_id' => array (
+     'cv_id' => array (
+       'name' => 'sequence',
+     ),
+     'name' => 'mRNA',
+     'is_obsolete' => 0
+   ),
  );
  *   $result = tripal_core_chado_update('feature',$umatch,$uvalues);
  * @endcode
@@ -1413,18 +1413,30 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *   option of 'order_by' may be used to sort results in the base table
  *   if more than one are returned.  The options must be compatible with
  *   the options accepted by the tripal_core_chado_select() function.
- *   Additionally,  The option 'return_array' can be provided to force
- *   the function to always return an array. Default behavior is to return
- *   a single record if only one record exists or to return an array if
- *   multiple records exist.
+ *   Additionally,  These options are available for this function:
+ *   -return_array: 
+ *     can be provided to force the function to always return an array. Default 
+ *     behavior is to return a single record if only one record exists or to return 
+ *     an array if multiple records exist.
+ *  - include_fk: 
+ *     an array of FK relationships to fallow. By default, the 
+ *     tripal_core_chado_select function will follow all FK relationships but this
+ *     may generate more queries then is desired.  Provide an array specifying the
+ *     fields to include.  For example, if including the cvterm, cv and dbxref records
+ *     for a property the following array would work:
+ *        array('type_id' => array('cv_id' => 1, 'dbxref_id' => 1)).
+ *     Typicall, to expadn a property, this function would also include the db record 
+ *     through the db_id foreign key with the dbxref and db tables, but becuase 
+ *     it is not included in the array it will not be included in the results.
  * @return
  *   Either an object (if only one record was selected from the base table)
  *   or an array of objects (if more than one record was selected from the base table).
+ *   If the option 'return_array' is provided the function always returns an array.
  *
  * Example Usage:
  * @code
  $values = array(
- 'name' => 'Medtr4g030710'
+   'name' => 'Medtr4g030710'
  );
  $features = tripal_core_generate_chado_var('feature', $values);
  * @endcode
@@ -1438,7 +1450,7 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *      this hook to return an array of fields to be excluded. For example:
  * @code
  mymodule_exclude_field_from_feature_by_default() {
- return array('residues' => TRUE);
+   return array('residues' => TRUE);
  }
  * @endcode
  *      will ensure that feature.residues is ecluded from a feature object by default.
@@ -1449,7 +1461,7 @@ function tripal_core_chado_get_foreign_key($table_desc, $field, $values, $option
  *      any table. Tokens available in criteria are >field_value<  and >field_name< . For example:
  * @code
  mymodule_exclude_type_by_default() {
- return array('text' => 'length(>field_value< ) > 50');
+   return array('text' => 'length(>field_value< ) > 50');
  }
  * @endcode
  *      will exclude all text fields with a length > 50. Thus if $feature.residues is longer than 50 *      it will be excluded, otherwise it will be added.
@@ -1463,6 +1475,10 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
   if(array_key_exists('return_array', $base_options)){
   	$return_array = 1;
   }
+  $include_fk = 0;
+  if(array_key_exists('include_fk', $base_options)){
+    $include_fk = $base_options['include_fk'];
+  }
 
   // get description for the current table----------------------------------------------------------
   $table_desc = tripal_core_get_chado_table_schema($table);
@@ -1606,9 +1622,25 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
             if (empty($object->{$foreign_key})) {
               continue;
             }
+            
+            if ($include_fk) {
+            	// don't recurse if the callee has supplied an $fk_include list and this 
+              // FK table is not in the list.
+            	if(is_array($include_fk) and !array_key_exists($foreign_key, $include_fk)){
+                continue;
+            	}
+            	// if we have the option but it is not an array then we don't recurse any furutehr
+            	if (!is_array($include_fk)) {
+            		continue;
+            	}	
+            } 
             // get the record from the foreign table
             $foreign_values = array($primary_key => $object->{$foreign_key});
-            $foreign_object = tripal_core_generate_chado_var($foreign_table, $foreign_values);
+            $options = array();
+            if(is_array($include_fk)){            	
+              $options['include_fk'] = $include_fk[$foreign_key];
+            }
+            $foreign_object = tripal_core_generate_chado_var($foreign_table, $foreign_values, $options);
             // add the foreign record to the current object in a nested manner
             $object->{$foreign_key} = $foreign_object;
             // Flatten expandable_x arrays so only in the bottom object
@@ -1692,17 +1724,17 @@ function tripal_core_generate_chado_var($table, $values, $base_options = array()
  *
  * Example Usage:
  * @code
- // Get a chado object to be expanded
- $values = array(
- 'name' => 'Medtr4g030710'
- );
- $features = tripal_core_generate_chado_var('feature', $values);
- // Expand the organism node
- $feature = tripal_core_expand_chado_vars($feature, 'node', 'organism');
- // Expand the feature.residues field
- $feature = tripal_core_expand_chado_vars($feature, 'field', 'feature.residues');
- // Expand the feature properties (featureprop table)
- $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureprop');
+   // Get a chado object to be expanded
+   $values = array(
+     'name' => 'Medtr4g030710'
+   );
+   $features = tripal_core_generate_chado_var('feature', $values);
+   // Expand the organism node
+   $feature = tripal_core_expand_chado_vars($feature, 'node', 'organism');
+   // Expand the feature.residues field
+   $feature = tripal_core_expand_chado_vars($feature, 'field', 'feature.residues');
+   // Expand the feature properties (featureprop table)
+   $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureprop');
  * @endcode
  *
  * @ingroup tripal_chado_api
@@ -1753,6 +1785,11 @@ function tripal_core_expand_chado_vars($object, $type, $to_expand, $table_option
       break;
     case "table": //--------------------------------------------------------------------------------
       $foreign_table = $to_expand;
+      
+      // don't expand the table it already is expanded
+      if(array_key_exists($foreign_table, $object)){
+      	return;
+      }
       $foreign_table_desc = tripal_core_get_chado_table_schema($foreign_table);
       // If it's connected to the base table
       if ($foreign_table_desc['foreign keys'][$base_table]) {
@@ -1788,8 +1825,14 @@ function tripal_core_expand_chado_vars($object, $type, $to_expand, $table_option
               $object->expanded = $to_expand;
             }
           }
+          // if the object returned is NULL then handle that
           else {
-            $object->{$foreign_table} = NULL;  
+          	if (count($foreign_table_desc['foreign keys'][$base_table]['columns']) > 1) {
+              $object->{$foreign_table}->{$left} = NULL;                 
+          	}
+          	else {
+          		$object->{$foreign_table} = NULL;
+          	}
           }
         }
       }

+ 94 - 98
tripal_feature/tripal_feature.module

@@ -1957,28 +1957,19 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   $feature = $variables['node']->feature;
    
   // expand the feature object to include the feature relationships.
-  $feature = tripal_core_expand_chado_vars($feature,
-     'table','feature_relationship', array('order_by'=>array('rank' => 'ASC')));
+  $options = array(
+    'return_array' => 1,
+    'order_by'     => array('rank' => 'ASC'),
+  );
+  $feature = tripal_core_expand_chado_vars($feature, 'table',
+    'feature_relationship', $options);
 
   // get the subject relationships
   $srelationships = $feature->feature_relationship->subject_id;
-  if (!$srelationships) {
-     $srelationships = array();
-  } 
-  elseif (!is_array($srelationships)) { 
-     $srelationships = array($srelationships); 
-  }
-  
-  // get the object relationships
   $orelationships = $feature->feature_relationship->object_id;
-  if (!$orelationships) {
-     $orelationships = array();
-  } 
-  elseif (!is_array($orelationships)) { 
-     $orelationships = array($orelationships); 
-  }
   
-  // get alignment as child
+  // get alignment as child. The $feature->featureloc element
+  // is already populated from the alignment preprocess function
   $cfeaturelocs = $feature->featureloc->feature_id;
   if (!$cfeaturelocs) {
      $cfeaturelocs = array();
@@ -1986,23 +1977,21 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   elseif (!is_array($cfeaturelocs)) { 
      $cfeaturelocs = array($cfeaturelocs); 
   }
-
   
   // prepare the SQL statement to get the featureloc for the 
   // feature in the relationships. 
-  if(!tripal_core_is_sql_prepared('sel_featureloc_preprocess_relationships')){
-    $psql = "PREPARE sel_featureloc_preprocess_relationships (int, int) AS " .
-            "SELECT FL.featureloc_id, F.name as srcfeature_name, FL.srcfeature_id, ".
-            "  FL.feature_id, FL.fmin, FL.fmax, FL.strand, FL.phase ".
-            "FROM featureloc FL " .
-            "  INNER JOIN feature F ON F.feature_id = FL.srcfeature_id ".
-            "WHERE FL.feature_id = $1 and FL.srcfeature_id = $2";
-    $prepared = chado_query($psql);
-    if(!$prepared){
-      watchdog('tripal_feature', "tripal_feature_preprocess_tripal_feature_relationships: not able to prepare '%name' statement for: %sql", array('%name' => 'sel_featureloc_preprocess_relationships', '%sql' => $psql), 'WATCHDOG ERROR');
-      return FALSE;
-    }
-  }  
+  $connection = tripal_db_persistent_chado();
+  $psql = " 
+    PREPARE sel_featureloc_preprocess_relationships (int, int) AS 
+    SELECT 
+      FL.featureloc_id, F.name as srcfeature_name, FL.srcfeature_id,
+      FL.feature_id, FL.fmin, FL.fmax, FL.strand, FL.phase
+    FROM featureloc FL 
+      INNER JOIN feature F ON F.feature_id = FL.srcfeature_id
+    WHERE FL.feature_id = $1 and FL.srcfeature_id = $2
+  ";
+  tripal_core_chado_prepare('sel_featureloc_preprocess_relationships', $psql, array('int', 'int'));
+
   
   // combine both object and subject relationshisp into a single array
   $relationships = array();
@@ -2010,76 +1999,80 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
   $relationships['subject'] = array();
   
   // iterate through the object relationships
-  foreach ($orelationships as $relationship) {
-     $rel = new stdClass(); 
-     // get locations where the child feature and this feature overlap with the
-     // same landmark feature.
-     $rel->child_featurelocs = array();     
-     foreach ($cfeaturelocs as $featureloc) {
-        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
-          $relationship->subject_id->feature_id, 
-          $featureloc->srcfeature_id->feature_id);        
-        while ($loc = db_fetch_object($res)){
-           // add in the node id of the src feature if it exists and save this location
-           $loc->nid = $featureloc->srcfeature_id->nid;
-           $rel->child_featurelocs[] = $loc;
-        }
-     }
-     $rel->record = $relationship;    
-     
-     // get the relationship and child types
-     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
-     $child_type = $relationship->subject_id->type_id->name;
-     
-     // get the node id of the subject
-     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
-     $n = db_fetch_object(db_query($sql,$relationship->subject_id->feature_id));
-     if($n){
-        $rel->record->nid = $n->nid;
-     }
-
-     if (!array_key_exists($rel_type, $relationships['object'])) {
-       $relationships['object'][$rel_type] = array();   
-     }
-     if (!array_key_exists($child_type, $relationships['object'][$rel_type])) {
-       $relationships['object'][$rel_type][$child_type] = array();   
-     }
-     $relationships['object'][$rel_type][$child_type][] = $rel;     
+  if ($orelationships) {
+	  foreach ($orelationships as $relationship) {
+	     $rel = new stdClass(); 
+	     // get locations where the child feature and this feature overlap with the
+	     // same landmark feature.
+	     $rel->child_featurelocs = array();     
+	     foreach ($cfeaturelocs as $featureloc) {
+	        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
+	          $relationship->subject_id->feature_id, 
+	          $featureloc->srcfeature_id->feature_id);        
+	        while ($loc = db_fetch_object($res)){
+	           // add in the node id of the src feature if it exists and save this location
+	           $loc->nid = $featureloc->srcfeature_id->nid;
+	           $rel->child_featurelocs[] = $loc;
+	        }
+	     }
+	     $rel->record = $relationship;    
+	     
+	     // get the relationship and child types
+	     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
+	     $child_type = $relationship->subject_id->type_id->name;
+	     
+	     // get the node id of the subject
+	     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
+	     $n = db_fetch_object(db_query($sql,$relationship->subject_id->feature_id));
+	     if($n){
+	        $rel->record->nid = $n->nid;
+	     }
+	
+	     if (!array_key_exists($rel_type, $relationships['object'])) {
+	       $relationships['object'][$rel_type] = array();   
+	     }
+	     if (!array_key_exists($child_type, $relationships['object'][$rel_type])) {
+	       $relationships['object'][$rel_type][$child_type] = array();   
+	     }
+	     $relationships['object'][$rel_type][$child_type][] = $rel;     
+	  }
   }
   
   // now add in the subject relationships
-  foreach ($srelationships as $relationship) {
-     $rel = new stdClass(); 
-     // get locations where this feature overlaps with the parent
-     $rel->parent_featurelocs = array();     
-     foreach ($cfeaturelocs as $featureloc) {
-        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
-          $relationship->object_id->feature_id, 
-          $featureloc->srcfeature_id->feature_id);
-        while ($loc = db_fetch_object($res)){
-           // add in the node id of the src feature if it exists and save this location
-           $loc->nid = $featureloc->srcfeature_id->nid;
-           $rel->parent_featurelocs[] = $loc;
-        }
-     }
-     $rel->record = $relationship;
-     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
-     $parent_type = $relationship->object_id->type_id->name;
-     
-     // get the node id of the subject
-     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
-     $n = db_fetch_object(db_query($sql,$relationship->object_id->feature_id));
-     if($n){
-        $rel->record->nid = $n->nid;
-     }
-     
-     if (!array_key_exists($rel_type, $relationships['subject'])) {
-       $relationships['subject'][$rel_type] = array();   
-     }
-     if (!array_key_exists($child_type, $relationships['subject'][$rel_type])) {
-       $relationships['subject'][$rel_type][$parent_type] = array();   
-     }
-     $relationships['subject'][$rel_type][$parent_type][] = $rel;
+  if ($srelationships) {
+	  foreach ($srelationships as $relationship) {
+	     $rel = new stdClass(); 
+	     // get locations where this feature overlaps with the parent
+	     $rel->parent_featurelocs = array();     
+	     foreach ($cfeaturelocs as $featureloc) {
+	        $res = chado_query("EXECUTE sel_featureloc_preprocess_relationships (%d, %d)", 
+	          $relationship->object_id->feature_id, 
+	          $featureloc->srcfeature_id->feature_id);
+	        while ($loc = db_fetch_object($res)){
+	           // add in the node id of the src feature if it exists and save this location
+	           $loc->nid = $featureloc->srcfeature_id->nid;
+	           $rel->parent_featurelocs[] = $loc;
+	        }
+	     }
+	     $rel->record = $relationship;
+	     $rel_type = t(preg_replace('/_/'," ",$relationship->type_id->name));
+	     $parent_type = $relationship->object_id->type_id->name;
+	     
+	     // get the node id of the subject
+	     $sql = "SELECT nid FROM chado_feature WHERE feature_id = %d";
+	     $n = db_fetch_object(db_query($sql,$relationship->object_id->feature_id));
+	     if($n){
+	        $rel->record->nid = $n->nid;
+	     }
+	     
+	     if (!array_key_exists($rel_type, $relationships['subject'])) {
+	       $relationships['subject'][$rel_type] = array();   
+	     }
+	     if (!array_key_exists($child_type, $relationships['subject'][$rel_type])) {
+	       $relationships['subject'][$rel_type][$parent_type] = array();   
+	     }
+	     $relationships['subject'][$rel_type][$parent_type][] = $rel;
+	  }
   }
   $feature->all_relationships = $relationships;
 
@@ -2092,6 +2085,9 @@ function tripal_feature_preprocess_tripal_feature_relationships(&$variables) {
 function tripal_feature_preprocess_tripal_feature_alignments(&$variables) {
   // we want to provide a new variable that contains the matched features.
   $feature = $variables['node']->feature;
+
+  $feature = tripal_core_expand_chado_vars($feature, 'table', 'featureloc');
+  $variables['node']->feature = $feature;
   
   // get alignments as child
   $cfeaturelocs = $feature->featureloc->feature_id;