Explorar o código

Changed MViews to accept a Schema API array. It is still backwards compatible and can accept old style postgres column definitions. Also, MViews created with a Drupal API schema array are automatically integreated as a custom table and therefore can be used to join with other MViews or Chado tables in the Views Integration

Stephen Ficklin %!s(int64=13) %!d(string=hai) anos
pai
achega
a56102450e

+ 207 - 66
tripal_core/mviews.php

@@ -11,7 +11,11 @@
  */
 
 /**
- * Add a materialized view to the chado database to help speed data access.
+ * Add a materialized view to the chado database to help speed data access. This
+ * function supports the older style where postgres column specifications 
+ * are provided using the $mv_table, $mv_specs and $indexed variables. It also
+ * supports the newer preferred method where the materialized view is described
+ * using the Drupal Schema API array.  
  *
  * @param $name 
  *   The name of the materialized view.
@@ -26,22 +30,36 @@
  * @param $query 
  *   The SQL query that loads the materialized view with data
  * @param $special_index  
- *   function
+ *   currently not used
+ * @param $comment
+ *   A string containing a description of the materialized view
+ * @param $mv_schema
+ *   If using the newer Schema API array to define the materialized view then
+ *   this variable should contain the array.
  *
  * @ingroup tripal_mviews_api
  */
-function tripal_add_mview ($name,$modulename,$mv_table,$mv_specs,$indexed,$query,$special_index,$comment=NULL){
+function tripal_add_mview ($name, $modulename, $mv_table, $mv_specs, $indexed,
+   $query, $special_index, $comment=NULL, $mv_schema=NULL)
+{
+   // get the table name from the schema array
+   $schema_arr = array();
+   if($mv_schema){
+      // get the schema from the mv_specs and use it to add the custom table
+      eval("\$schema_arr = $mv_schema;");
+      $mv_table = $schema_arr['table'];
+   }
 
    $record = new stdClass();
    $record->name = $name;
    $record->modulename = $modulename;
-   $record->mv_schema = 'DUMMY';
    $record->mv_table = $mv_table;
    $record->mv_specs = $mv_specs;
    $record->indexed = $indexed;
    $record->query = $query;
    $record->special_index = $special_index;
    $record->comment = $comment;
+   $record->mv_schema = $mv_schema;
 
    // add the record to the tripal_mviews table and if successful
    // create the new materialized view in the chado schema
@@ -67,24 +85,34 @@ function tripal_add_mview ($name,$modulename,$mv_table,$mv_specs,$indexed,$query
         }
       }
 
-      // add the table to the database
-      $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index"; 
-      $previous_db = tripal_db_set_active('chado');  // use chado database
-      $results = db_query($sql);
-      tripal_db_set_active($previous_db);  // now use drupal database
-      if($results){
-         drupal_set_message(t("View '$name' created"));
+      // create the table differently depending on if it the traditional method
+      // or the Drupal Schema API method
+      if($mv_schema){
+         if(!tripal_create_chado_table ($ret,$mv_table,$schema_arr)){
+            drupal_set_message("Could not create the materialized view. Check Drupal error report logs.");
+         } else {
+            drupal_set_message(t("View '$name' created"));
+         }
       } else {
-         // if we failed to create the view in chado then
-         // remove the record from the tripal_jobs table
-         $sql = "DELETE FROM {tripal_mviews} ".
-                "WHERE mview_id = $record->mview_id";
-         db_query($sql);
+         // add the table to the database
+         $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index"; 
+         $previous_db = tripal_db_set_active('chado');  // use chado database
+         $results = db_query($sql);
+         tripal_db_set_active($previous_db);  // now use drupal database
+         if($results){
+            drupal_set_message(t("View '$name' created"));
+         } else {
+            drupal_set_message(t("Failed to create the materialized view table: '$mv_table'"));
+         }
       }
    }
 }
 /**
- * Edits a materialized view to the chado database to help speed data access.
+ * Edits a materialized view to the chado database to help speed data access.This
+ * function supports the older style where postgres column specifications 
+ * are provided using the $mv_table, $mv_specs and $indexed variables. It also
+ * supports the newer preferred method where the materialized view is described
+ * using the Drupal Schema API array.  
  *
  * @param $mview_id 
  *   The mview_id of the materialized view to edit
@@ -101,17 +129,32 @@ function tripal_add_mview ($name,$modulename,$mv_table,$mv_specs,$indexed,$query
  * @param $query 
  *   The SQL query that loads the materialized view with data
  * @param $special_index  
- *   function
+ *   currently not used
+ * @param $comment
+ *   A string containing a description of the materialized view
+ * @param $mv_schema
+ *   If using the newer Schema API array to define the materialized view then
+ *   this variable should contain the array.
  *
  * @ingroup tripal_mviews_api
  */
-function tripal_edit_mview ($mview_id,$name,$modulename,$mv_table,$mv_specs,$indexed,$query,$special_index,$comment){
+function tripal_edit_mview ($mview_id,$name,$modulename,$mv_table,$mv_specs,
+   $indexed,$query,$special_index,$comment=NULL,$mv_schema=NULL)
+{
+
+   // get the table name from the schema array
+   $schema_arr = array();
+   if($mv_schema){
+      // get the schema from the mv_specs and use it to add the custom table
+      eval("\$schema_arr = $mv_schema;");
+      $mv_table = $schema_arr['table'];
+   }
 
    $record = new stdClass();
    $record->mview_id = $mview_id;
    $record->name = $name;
    $record->modulename = $modulename;
-   $record->mv_schema = 'DUMMY';
+   $record->mv_schema = $mv_schema;
    $record->mv_table = $mv_table;
    $record->mv_specs = $mv_specs;
    $record->indexed = $indexed;
@@ -154,20 +197,24 @@ function tripal_edit_mview ($mview_id,$name,$modulename,$mv_table,$mv_specs,$ind
            $index .= "CREATE INDEX idx_${mv_table}_${field} ON $mv_table ($field);";
         }
       }
-
-      // recreate the view
-      $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index"; 
-      $previous_db = tripal_db_set_active('chado');  // use chado database
-      $results = db_query($sql);
-      tripal_db_set_active($previous_db);  // now use drupal database
-      if($results){
-         drupal_set_message(t("View '$name' edited and saved.  All results cleared. Please re-populate the view."));
+      // re-create the table differently depending on if it the traditional method
+      // or the Drupal Schema API method
+      if($mv_schema){         
+         if(!tripal_create_chado_table ($ret,$mv_table,$schema_arr)){
+            drupal_set_message("Could not create the materialized view. Check Drupal error report logs.");
+         } else {
+            drupal_set_message(t("View '$name' created"));
+         }
       } else {
-         // if we failed to create the view in chado then
-         // remove the record from the tripal_jobs table
-         $sql = "DELETE FROM {tripal_mviews} ".
-                "WHERE mview_id = $record->mview_id";
-         db_query($sql);
+         $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index"; 
+         $previous_db = tripal_db_set_active('chado');  // use chado database
+         $results = db_query($sql);
+         tripal_db_set_active($previous_db);  // now use drupal database
+         if($results){
+            drupal_set_message(t("View '$name' edited and saved.  All results cleared. Please re-populate the view."));
+         } else {
+            drupal_set_message(t("Failed to create the materialized view table: '$mv_table'"));
+         }
       }
    }
 }
@@ -251,10 +298,10 @@ function tripal_update_mview ($mview_id){
    if($mview){
       $previous_db = tripal_db_set_active('chado');  // use chado database
 	   $results = db_query("DELETE FROM {$mview->mv_table}");
-      $results = db_query("INSERT INTO $mview->mv_table ($mview->query)");
+      $results = db_query("INSERT INTO {$mview->mv_table} ($mview->query)");
       tripal_db_set_active($previous_db);  // now use drupal database
       if($results){
-         $sql = "SELECT count(*) as cnt FROM $mview->mv_table";
+         $sql = "SELECT count(*) as cnt FROM {$mview->mv_table}";
          $count = db_fetch_object(db_query($sql));
 	      $record = new stdClass();
          $record->mview_id = $mview_id;
@@ -413,9 +460,9 @@ function tripal_mviews_form(&$form_state = NULL,$mview_id = NULL){
 
    // get this requested view
    if(strcmp($action,'Edit')==0){
-      $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = $mview_id ";
-      $mview = db_fetch_object(db_query($sql));
-
+      $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d ";
+      $mview = db_fetch_object(db_query($sql,$mview_id));
+      
       # set the default values.  If there is a value set in the 
       # form_state then let's use that, otherwise, we'll pull 
       # the values from the database 
@@ -446,6 +493,26 @@ function tripal_mviews_form(&$form_state = NULL,$mview_id = NULL){
       }
       if(!$default_comment){
          $default_comment = $mview->comment;
+      }      
+      if(!$default_schema){
+         $default_schema = $mview->mv_schema;
+      }
+      // the mv_table column of the tripal_mviews table always has the table 
+      // name even if it is a custom table. However, for the sake of the form,
+      // we do not want this to show up as the mv_table is needed for the 
+      // traditional style input.  We'll blank it out if we have a custom 
+      // table and it will get reset in the submit function using the 
+      // 'table' value from the schema array
+      if($default_schema){
+         $default_mv_table = '';
+      }
+      
+      // set which fieldset is collapsed 
+      $schema_collapsed = 0;      
+      $traditional_collapsed = 1;
+      if(!$default_schema){
+         $schema_collapsed = 1;      
+         $traditional_collapsed = 0;
       }
    }
    // Build the form
@@ -463,58 +530,80 @@ function tripal_mviews_form(&$form_state = NULL,$mview_id = NULL){
       '#description'   => t('Please enter the name for this materialized view.'),
       '#required'      => TRUE,
       '#default_value' => $default_name,
-      '#weight'        => 1
+   );
+   $form['comment']= array(
+      '#type'          => 'textarea',
+      '#title'         => t('MView Description'),
+      '#description'   => t('Optional.  Please provide a description of the purpose for this materialized vieww.'),
+      '#required'      => FALSE,
+      '#default_value' => $default_comment,
    );
 
-   $form['mv_table']= array(
+   // add a fieldset for the Drupal Schema API
+   $form['schema'] = array(
+     '#type' => 'fieldset',
+     '#title' => 'Drupal Schema API Setup',
+     '#description' => t('Use the Drupal Schema API array to describe a table. The benefit is that it '.
+                         'can be fully integrated with Tripal Views.  Tripal supports an extended '.
+                         'array format to allow for descriptoin of foreign key relationships.'),
+     '#collapsible' => 1,
+     '#collapsed' => $schema_collapsed ,
+   );
+   $form['schema']['schema']= array(
+      '#type'          => 'textarea',
+      '#title'         => t('Schema Array'),
+      '#description'   => t('Please enter the Drupal Schema API compatible array that defines the table.'),
+      '#required'      => FALSE,
+      '#default_value' => $default_schema,
+      '#rows'          => 25,
+   ); 
+   // add a fieldset for the Original Table Description fields
+   $form['traditional'] = array(
+     '#type' => 'fieldset',
+     '#title' => 'Traditional MViews Setup',
+     '#description' => t('Traidtionally with Tripal MViews were created by specifying PostgreSQL style '.
+                         'column types.  This method can be used but is deprecated in favor of the '.
+                         'newer Drupal schema API method provided above.'),
+     '#collapsible' => 1,
+     '#collapsed' => $traditional_collapsed,
+   ); 
+   $form['traditional']['mv_table']= array(
       '#type'          => 'textfield',
       '#title'         => t('Table Name'),
-      '#description'   => t('Please enter the Postgres table name that this view will generate in the database.  You can use the schema and table name for querying the view'),
-      '#required'      => TRUE,
+      '#description'   => t('Please enter the table name that this view will generate in the database.  You can use the schema and table name for querying the view'),
+      '#required'      => FALSE,
       '#default_value' => $default_mv_table,
-      '#weight'        => 3
    );
-   $form['mv_specs']= array(
+   $form['traditional']['mv_specs']= array(
       '#type'          => 'textarea',
       '#title'         => t('Table Definition'),
       '#description'   => t('Please enter the field definitions for this view. Each field should be separated by a comma or enter each field definition on each line.'),
-      '#required'      => TRUE,
+      '#required'      => FALSE,
       '#default_value' => $default_mv_specs,
-      '#weight'        => 4
    );
-   $form['indexed']= array(
+   $form['traditional']['indexed']= array(
       '#type'          => 'textarea',
       '#title'         => t('Indexed Fields'),
       '#description'   => t('Please enter the field names (as provided in the table definition above) that will be indexed for this view.  Separate by a comma or enter each field on a new line.'),
       '#required'      => FALSE,
       '#default_value' => $default_indexed,
-      '#weight'        => 5
-   );
-   $form['mvquery']= array(
-      '#type'          => 'textarea',
-      '#title'         => t('Query'),
-      '#description'   => t('Please enter the SQL statement used to populate the table.'),
-      '#required'      => TRUE,
-      '#default_value' => $default_mvquery,
-      '#weight'        => 6
    );
 /**
-   $form['special_index']= array(
+   $form['traditional']['special_index']= array(
       '#type'          => 'textarea',
       '#title'         => t('View Name'),
       '#description'   => t('Please enter the name for this materialized view.'),
       '#required'      => TRUE,
       '#default_value' => $default_special_index,
-      '#weight'        => 7
    );
 */
-   $form['comment']= array(
+   $form['mvquery']= array(
       '#type'          => 'textarea',
-      '#title'         => t('MView Description'),
-      '#description'   => t('Optional.  Please provide a description of the purpose for this materialized vieww.'),
-      '#required'      => FALSE,
-      '#default_value' => $default_comment,
-      '#weight'        => 8
+      '#title'         => t('Query'),
+      '#description'   => t('Please enter the SQL statement used to populate the table.'),
+      '#required'      => TRUE,
+      '#default_value' => $default_mvquery,
+      '#rows'          => 25,
    );
    if($action == 'Edit'){
       $value = 'Save';
@@ -537,7 +626,56 @@ function tripal_mviews_form(&$form_state = NULL,$mview_id = NULL){
 *
 * @ingroup tripal_core
 */
+function tripal_mviews_form_validate($form, &$form_state){
+   $action = $form_state['values']['action'];
+   $mview_id = $form_state['values']['mview_id'];
+   $name = $form_state['values']['name'];
+   $mv_table = $form_state['values']['mv_table'];
+   $mv_specs = $form_state['values']['mv_specs'];
+   $indexed = $form_state['values']['indexed'];
+   $query = $form_state['values']['mvquery'];
+   $special_index = $form_state['values']['special_index'];
+   $comment = $form_state['values']['comment'];
+   $schema = $form_state['values']['schema'];
+   
+   if($schema and ($mv_table or $mv_specs or $indexed or $special_index)){
+       form_set_error($form_state['values']['schema'], 
+          t('You can create an MView using the Drupal Schema API method or the '.
+            'traditional method but not both.'));
+   }
+   if(!$schema){
+      if(!$mv_speces){
+         form_set_error($form_state['values']['mv_specs'], 
+            t('The Table Definition field is required.'));
+      }
+      if(!$mv_table){
+         form_set_error($form_state['values']['mv_table'], 
+            t('The Table Name field is required.'));
+      }
+   }
+   
+   // make sure the array is valid
+   if($schema){
+      $success = eval("\$schema_array = $schema;");
+      if ($success === FALSE){
+         $error = error_get_last();
+         form_set_error($form_state['values']['schema'], 
+            t("The schema array is improperly formatted. Parse Error : " . $error["message"]));
+      }
+      if(!array_key_exists('table',$schema_array)){
+         form_set_error($form_state['values']['schema'], 
+            t("The schema array must have key named 'table'"));
+      } 
+      // TODO: add in more validation checks of the array to help the user
+   }
+}
+/**
+*
+*
+* @ingroup tripal_core
+*/
 function tripal_mviews_form_submit($form, &$form_state){
+   $ret = array();
    
    $action = $form_state['values']['action'];
    $mview_id = $form_state['values']['mview_id'];
@@ -548,12 +686,15 @@ function tripal_mviews_form_submit($form, &$form_state){
    $query = $form_state['values']['mvquery'];
    $special_index = $form_state['values']['special_index'];
    $comment = $form_state['values']['comment'];
+   $schema = $form_state['values']['schema'];
 
    if(strcmp($action,'Edit')==0){
-      tripal_edit_mview($mview_id,$name, 'tripal_core',$mv_table, $mv_specs,$indexed,$query,$special_index,$comment);
+      tripal_edit_mview($mview_id,$name, 'tripal_core',$mv_table, $mv_specs,
+         $indexed,$query,$special_index,$comment,$schema);
    }
    else if(strcmp($action,'Add')==0){
-      tripal_add_mview ($name, 'tripal_core',$mv_table, $mv_specs,$indexed,$query,$special_index,$comment);
+      tripal_add_mview ($name, 'tripal_core',$mv_table, $mv_specs,
+         $indexed,$query,$special_index,$comment,$schema);
    }
    else {
         drupal_set_message("No action performed.");

+ 74 - 13
tripal_core/tripal_core.api.inc

@@ -1800,8 +1800,12 @@ function tripal_get_max_chado_rank ($tablename, $where_options) {
 /**
  * Add a new table to the Chado schema. This function is simply a wrapper for
  * the db_create_table() function of Drupal, but ensures the table is created
- * inside the Chado schema rather than the Drupal schema.
- *
+ * inside the Chado schema rather than the Drupal schema.  If the table already
+ * exists then it will be dropped and recreated using the schema provided.
+ * Howver, it will only drop a table if it exsits in the tripal_custom_tables
+ * table. This way the function cannot be used to accidentally alter existing
+ * non custom tables.
+ * 
  * @param $ret
  *   Array to which query results will be added.
  * @param $table
@@ -1816,21 +1820,78 @@ function tripal_get_max_chado_rank ($tablename, $where_options) {
  */
 function tripal_create_chado_table (&$ret,$table,$schema) {
    $ret = array();
-   
-   $previous_db = tripal_db_set_active('chado');  // use chado database
-   db_create_table($ret,$table,$schema);
+
+   // If the table exits in Chado but not in the tripal_custom_tables field
+   // then call an error.  if the table exits in the tripal_custom_tables but
+   // not in Chado then create the table and replace the entry.
+   $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_name = '%s'";
+   $centry = db_fetch_object(db_query($sql,$table));
+   $previous_db = tripal_db_set_active('chado');  // use chado database   
+   $exists = db_table_exists($table);
    tripal_db_set_active($previous_db);  // now use drupal database
+   if(!$exists){
+      $previous_db = tripal_db_set_active('chado');  // use chado database   
+      db_create_table($ret,$table,$schema);
+      tripal_db_set_active($previous_db);  // now use drupal database  
+      if(count($ret)==0){
+   	   watchdog('tripal_core', "Error adding custom table '!table_name'.", 
+   	      array('!table_name' => $table), WATCHDOG_ERROR); 
+         return FALSE;
+      }       
+   }
+   if($exists and !$centry){
+   	watchdog('tripal_core', "Could not add custom table '!table_name'. It ".
+   	         "already exists but is not known to Tripal as being a custom table.", 
+   	   array('!table_name' => $table), WATCHDOG_WARNING);       
+   	   return FALSE;
+   }
+   if($exists and $centry){
+      // drop the table we'll recreate it with the new schema
+      $previous_db = tripal_db_set_active('chado');  // use chado database   
+      db_drop_table($ret,$table);
+      db_create_table($ret,$table,$schema);
+      tripal_db_set_active($previous_db);  // now use drupal database        
+   }
    
    // if the table creation was succesful then add an entry
    // in the tripal_custom_table
-   if($ret){
-      $record = new stdClass();
-      $record->table_name = $table;
-      $record->schema = serialize($schema);
-      $success = drupal_write_record('tripal_custom_tables',$record);
-      if(!$success){
-         drupal_set_message($message,"Error adding custom table: $table");   
-      }
+   $record = new stdClass();
+   $record->table_name = $table;
+   $record->schema = serialize($schema);
+   // if an entry already exists then remove it
+   if($centry){
+      $sql = "DELETE FROM {tripal_custom_tables} WHERE table_name = '%s'";
+      db_query($sql,$table);
+   } 
+   $success = drupal_write_record('tripal_custom_tables',$record);
+   if(!$success){
+	   watchdog('tripal_core', "Error adding custom table.", 
+	      array('!table_name' => $table), WATCHDOG_ERROR); 
+      return FALSE;
    }
    return $ret;
 }
+/**
+ * Retrieves the schema in an array for the specified custom table.
+ * 
+ * @param $table
+ *   The name of the table to create.
+ *
+ * @return 
+ *   A Drupal-style Schema API array definition of the table. Returns
+ *   FALSE on failure.
+ *
+ * @ingroup tripal_core_api
+ */
+function tripal_get_chado_custom_schema ($table) {
+   $sql = "SELECT schema FROM {tripal_custom_tables} WHERE table_name = '%s'";
+   $custom = db_fetch_object(db_query($sql,$table));
+   if(!$custom){
+      return FALSE;
+   } 
+   else {
+      return unserialize($custom->schema);
+   }
+}
+
+

+ 22 - 4
tripal_core/tripal_core.install

@@ -28,9 +28,14 @@ function tripal_core_install(){
 * @ingroup tripal_feature
 */
 function tripal_core_update_6000(){
-   // recreate the materialized view
+   // add additional columsn to the tripal_mviews table
    db_add_field($ret, 'tripal_mviews', 'status', array('type' => 'text', 'size' => 'normal', 'not null' => FALSE));
    db_add_field($ret, 'tripal_mviews', 'comment', array('type' => 'text', 'size' => 'normal', 'not null' => FALSE));
+   db_add_field($ret, 'tripal_mviews', 'mv_schema', array('type' => 'text', 'size' => 'normal', 'not null' => FALSE));
+   db_change_field($ret, 'tripal_mviews', 'mv_table','mv_table',array('type' => 'varchar','length' => 128, 'not null' => FALSE));
+   db_change_field($ret, 'tripal_mviews', 'mv_specs','mv_specs',array('type' => 'text', 'size' => 'normal', 'not null' => FALSE));
+   db_change_field($ret, 'tripal_mviews', 'indexed','indexed',array('type' => 'text', 'size' => 'normal', 'not null' => FALSE));
+
    
    // create the custom tables table
    $ret = array();
@@ -51,6 +56,18 @@ function tripal_core_update_6000(){
 */
 function tripal_core_schema() {
    $schema = tripal_core_get_schemas();
+   
+   // if this module is already installed and enabled, then we want to provide
+   // the schemas for all of the custom tables.  This will allow Views to 
+   // see the schemas.  We check if the module is installed because during 
+   // installation we don't want to make these custom tables available as we don't
+   // want them created in the Drupal database.  The custom tables go in the 
+   // Chado database.
+   $sql = 'SELECT * FROM {tripal_custom_tables}';
+   $q = db_query($sql);
+   while($custom = db_fetch_object($q)){
+      $schema[$custom->table_name] = unserialize($custom->schema);
+   }
    return $schema;
 }
 /************************************************************************
@@ -100,9 +117,10 @@ function tripal_core_mviews_schema(){
          'mview_id'      => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
          'name'          => array('type' => 'varchar','length' => 255, 'not null' => TRUE),
          'modulename'    => array('type' => 'varchar','length' => 50, 'not null' => TRUE, 'description' => 'The module name that provides the callback for this job'),
-         'mv_table'      => array('type' => 'varchar','length' => 128, 'not null' => TRUE),
-         'mv_specs'      => array('type' => 'text', 'size' => 'normal', 'not null' => TRUE),
-         'indexed'       => array('type' => 'text', 'size' => 'normal', 'not null' => TRUE),
+         'mv_table'      => array('type' => 'varchar','length' => 128, 'not null' => FALSE),
+         'mv_specs'      => array('type' => 'text', 'size' => 'normal', 'not null' => FALSE),
+         'mv_schema'     => array('type' => 'text', 'size' => 'normal', 'not null' => FALSE),
+         'indexed'       => array('type' => 'text', 'size' => 'normal', 'not null' => FALSE),
          'query'         => array('type' => 'text', 'size' => 'normal', 'not null' => TRUE),
          'special_index' => array('type' => 'text', 'size' => 'normal', 'not null' => FALSE),
          'last_update'   => array('type' => 'int', 'not null' => FALSE, 'description' => 'UNIX integer time'),

+ 1 - 2
tripal_core/tripal_core.module

@@ -133,9 +133,8 @@ function tripal_core_menu() {
      'type' => MENU_CALLBACK,
    );
  
-
+   
    // Materialized Views 
-
    $items['admin/tripal/mviews'] = array(
      'title' => 'MViews',
      'description' => 'Materialized views are used to improve speed of large or complex queries.',

+ 22 - 10
tripal_views/tripal_views.views.inc

@@ -409,7 +409,7 @@ function tripal_views_add_node_ids_to_view (&$view) {
 
 function tripal_views_views_data(){   
   
-   // Define Global Fields -------------
+   // Define Global Fields 
    // Filter handler that lets the admin say: 
    // "Show no results until they enter search parameters"
    $data['views']['search_results'] = array(
@@ -442,7 +442,7 @@ function tripal_views_views_data(){
       $type_prefix = '';
 
       // populate the base table name and fields.  If an $mview_id is given
-      // the get the materialized view info, otherwise get the Chado table info
+      // then get the materialized view info, otherwise get the Chado table info
       if($mview_id){
          $type_prefix = 'MView';
          // get the base table name from the materialized view
@@ -475,10 +475,25 @@ function tripal_views_views_data(){
       else {
          $type_prefix = 'Chado Table';
          $base_table = $tvi_row->table_name;
+         // The chado table could be a regular Chado table or a custom table
+         // in the chado database.  Therefore we'll check both
          $table_desc = module_invoke_all('chado_'.$base_table.'_schema');
+         if(!$table_desc){            
+            $table_desc = tripal_get_chado_custom_schema($base_table);
+         }
          $fields = $table_desc['fields'];
          foreach($fields as $column => $attrs){
-            $base_fields[] = $column;
+            $base_fields[$column] = array(
+              'column_name' => $column,
+              'type' => $attrs['type'],
+            );
+         }
+         // get the field name and descriptions
+         $sql = "SELECT * FROM {tripal_views_field} WHERE setup_id=%d";
+         $query = db_query($sql, $setup_id);
+         while ($field = db_fetch_object($query)) {
+           $base_fields[$field->column_name]['name'] = $field->name;
+           $base_fields[$field->column_name]['help'] = $field->description;
          }
       }
 
@@ -489,7 +504,6 @@ function tripal_views_views_data(){
         'title' => "$type_prefix: $tvi_row->name",
         'help'  => $tvi_row->comment,
       );
-
       // first add the fields
       foreach ($base_fields as $column_name => $base_field){
         $data[$base_table][$column_name] = array(
@@ -499,7 +513,8 @@ function tripal_views_views_data(){
               'click sortable' => TRUE,
            ),
         );
-
+        
+        
         // now add the handlers
         $sql = "SELECT * FROM {tripal_views_handlers} WHERE setup_id = %d AND column_name = '%s'";
         $handlers = db_query($sql,$setup_id,$column_name);
@@ -525,9 +540,7 @@ function tripal_views_views_data(){
         // check to see if the join table is one that correlates with Drupal nodes
         // if so, there will be a chado_<table_name> table in the Drupal database
         // if there is, then we need to add the linking join information
-        $sql = "SELECT tablename FROM pg_tables WHERE tablename = 'chado_$left_table'";
-        if(db_fetch_object(db_query($sql))){
-
+        if(db_table_exists("chado_$left_table")){
            // join the mview to the linker table
            $data[$base_table]['table']['join']["chado_$left_table"] = array(
              'left_field' => $left_field,
@@ -575,8 +588,7 @@ function tripal_views_views_data_alter(&$data) {
         // if there is, then we need to add the linking join information.  We did
         // this step in the hook_views_data function above, but now we need 
         // to add the reciprical joins
-        $sql = "SELECT tablename FROM pg_tables WHERE tablename = '%s'";
-        if(db_fetch_object(db_query($sql,"chado_$left_table"))){
+        if(db_table_exists("chado_$left_table")){
 
            // join the linker table to the mview
            if(array_key_exists("chado_$left_table",$data)){

+ 28 - 7
tripal_views/tripal_views_integration.inc

@@ -304,12 +304,23 @@ function tripal_views_integration_form(&$form_state, $setup_id = NULL){
        $columns = explode(",",$mview->mv_specs);
     } else {
        $table_desc = module_invoke_all('chado_'.$table_name.'_schema');
-       $fields = $table_desc['fields'];
-       // iterate through the columns and build the format
-       // compatible with the code below. The column name is first followed
-       // by the type with a separating space
-       foreach($fields as $column => $attrs){
-          $columns[] = "$column ".$attrs['type'];
+       if($table_desc){
+          $fields = $table_desc['fields'];
+          // iterate through the columns and build the format
+          // compatible with the code below. The column name is first followed
+          // by the type with a separating space
+          foreach($fields as $column => $attrs){
+             $columns[] = "$column ".$attrs['type'];
+          }
+       }
+       
+       // now do the same for the custom tables
+       $table_desc = tripal_get_chado_custom_schema ($table_name);
+       if($table_desc){
+          $fields = $table_desc['fields'];
+          foreach($fields as $column => $attrs){
+             $columns[] = "$column ".$attrs['type'];
+          }
        }
     }
 
@@ -461,7 +472,12 @@ function tripal_views_integration_form(&$form_state, $setup_id = NULL){
       
       $columns = array();
       if($default_join_table){
+        // get the table description in the typical way and if it returns 
+        // nothing then get the custom table description
         $table_desc = module_invoke_all('chado_'.$default_join_table.'_schema');
+        if(!$table_desc){
+           $table_desc = tripal_get_chado_custom_schema ($default_join_table);
+        }
         foreach ($table_desc['fields'] as $column => $def){
            $columns[$column] = $column;
         }
@@ -831,9 +847,14 @@ function tripal_views_integration_form_submit($form, &$form_state){
       $left_column = $form_state['values']["fields_join_column_$table_id-$i"];
 
       if($left_column){
+         if($mview_id){
+            $base_table = $mview->mv_table;
+         } else {
+            $base_table = $table_name;
+         }
          $view_join_record = array(
            'setup_id' => $tripal_views_record['setup_id'],
-           'base_table' => $mview->mv_table,
+           'base_table' => $base_table,
            'base_field' => $key,
            'left_table' => $left_table,
            'left_field' => $left_column,