|  | @@ -542,6 +542,8 @@ function chado_insert_record($table, $values, $options = array()) {
 | 
	
		
			
				|  |  |   * 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.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | + * @TODO: Support Complex filtering as is done in chado_select_record();
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   * @ingroup tripal_chado_query_api
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  function chado_update_record($table, $match, $values, $options = NULL) {
 | 
	
	
		
			
				|  | @@ -783,6 +785,8 @@ function chado_update_record($table, $match, $values, $options = NULL) {
 | 
	
		
			
				|  |  |   * values to update.  The function will find all records that match the
 | 
	
		
			
				|  |  |   * columns specified and delete them.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | + * @TODO: Support Complex filtering as is done in chado_select_record();
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   * @ingroup tripal_chado_query_api
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  function chado_delete_record($table, $match, $options = NULL) {
 | 
	
	
		
			
				|  | @@ -892,7 +896,8 @@ function chado_delete_record($table, $match, $options = NULL) {
 | 
	
		
			
				|  |  |   * @param $values
 | 
	
		
			
				|  |  |   *  An associative array containing the values for filtering the results. In the
 | 
	
		
			
				|  |  |   *  case where multiple values for the same time are to be selected an additional
 | 
	
		
			
				|  |  | - *  entry for the field should appear for each value
 | 
	
		
			
				|  |  | + *  entry for the field should appear for each value. If you need to filter
 | 
	
		
			
				|  |  | + *  results using more complex methods see the 'Complex Filtering' section below.
 | 
	
		
			
				|  |  |   * @param $options
 | 
	
		
			
				|  |  |   *  An associative array of additional options where the key is the option
 | 
	
		
			
				|  |  |   *  and the value is the value of that option.
 | 
	
	
		
			
				|  | @@ -966,33 +971,44 @@ function chado_delete_record($table, $match, $options = NULL) {
 | 
	
		
			
				|  |  |   * for the cvterm is nested as well.  In the example above, two different species
 | 
	
		
			
				|  |  |   * are allowed to match
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | + * Complex Filtering:
 | 
	
		
			
				|  |  | + *   All of the documentation above supports filtering based on 'is equal to'
 | 
	
		
			
				|  |  | + *   or 'is NULL'. If your criteria doesn't fall into one of these two categories
 | 
	
		
			
				|  |  | + *   then you need to provide an array with additional details such as the operator
 | 
	
		
			
				|  |  | + *   as well as the value. An example follows and will be discussed in detail.
 | 
	
		
			
				|  |  | + *   @code
 | 
	
		
			
				|  |  | +      $columns = array('feature_id', 'fmin', 'fmax');
 | 
	
		
			
				|  |  | +      // Regular criteria specifying the parent feature to retrieve locations from.
 | 
	
		
			
				|  |  | +      $values = array(
 | 
	
		
			
				|  |  | +        'srcfeature_id' => array(
 | 
	
		
			
				|  |  | +          'uniquename' => 'MtChr01'
 | 
	
		
			
				|  |  | +          'type_id' => array(
 | 
	
		
			
				|  |  | +            'name' => 'pseudomolecule'
 | 
	
		
			
				|  |  | +          ),
 | 
	
		
			
				|  |  | +        ),
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      // Complex filtering to specify the range to return locations from.
 | 
	
		
			
				|  |  | +      $values['fmin'][] = array(
 | 
	
		
			
				|  |  | +        'op' => '>',
 | 
	
		
			
				|  |  | +        'data' => 15
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      $values['fmin'][] = array(
 | 
	
		
			
				|  |  | +        'op' => '<',
 | 
	
		
			
				|  |  | +        'data' => 100
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      $results = chado_select_record('featureloc', $columns, $values);
 | 
	
		
			
				|  |  | + *   @endcode
 | 
	
		
			
				|  |  | + *   The above code example will return all of the name, start and end of all
 | 
	
		
			
				|  |  | + *   the features that start within MtChr1:15-100bp. Note that complex filtering
 | 
	
		
			
				|  |  | + *   can be used in conjunction with basic filtering and that multiple criteria,
 | 
	
		
			
				|  |  | + *   even for the same field can be entered.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   * @ingroup tripal_chado_query_api
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  $print_errors = (isset($options['print_errors'])) ? $options['print_errors'] : FALSE;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (!is_array($values)) {
 | 
	
		
			
				|  |  | -    tripal_report_error('tripal_core', TRIPAL_ERROR, 'Cannot pass non array as values for selecting.',
 | 
	
		
			
				|  |  | -      array(), array('print' => $print_errors)
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -    return FALSE;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (!is_array($columns)) {
 | 
	
		
			
				|  |  | -    tripal_report_error('tripal_core', TRIPAL_ERROR, 'Cannot pass non array as columns for selecting.',
 | 
	
		
			
				|  |  | -      array(), array('print' => $print_errors)
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -    return FALSE;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (count($columns)==0) {
 | 
	
		
			
				|  |  | -    tripal_report_error('tripal_core', TRIPAL_ERROR, 'Cannot pass an empty array as columns for selecting.',
 | 
	
		
			
				|  |  | -      array(), array('print' => $print_errors)
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -    return FALSE;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // set defaults for options. If we don't set defaults then
 | 
	
		
			
				|  |  | -  // we get memory leaks when we try to access the elements
 | 
	
		
			
				|  |  | +  // 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();
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -1018,8 +1034,12 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |    if (array_key_exists('pager', $options)) {
 | 
	
		
			
				|  |  |      $pager = $options['pager'];
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  $print_errors = FALSE;
 | 
	
		
			
				|  |  | +  if (isset($options['print_errors'])) {
 | 
	
		
			
				|  |  | +    $print_errors = $options['print_errors'];
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // check that our columns and values arguments are proper arrays
 | 
	
		
			
				|  |  | +  // Check that our columns and values arguments are proper arrays.
 | 
	
		
			
				|  |  |    if (!is_array($columns)) {
 | 
	
		
			
				|  |  |      tripal_report_error('tripal_core', TRIPAL_ERROR,
 | 
	
		
			
				|  |  |        'chado_select_record; the $columns argument must be an array. Columns:%columns',
 | 
	
	
		
			
				|  | @@ -1037,8 +1057,9 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      return FALSE;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // get the table description
 | 
	
		
			
				|  |  | +  // Get the table description.
 | 
	
		
			
				|  |  |    $table_desc = chado_get_schema($table);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    $select = '';
 | 
	
		
			
				|  |  |    $from = '';
 | 
	
		
			
				|  |  |    $where = array();
 | 
	
	
		
			
				|  | @@ -1128,9 +1149,13 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // Process the values array into where clauses and retrieve foreign keys. The
 | 
	
		
			
				|  |  | +  // $where array should always be an integer-indexed array with each value
 | 
	
		
			
				|  |  | +  // being an array with a 'field', 'op', and 'data' keys with all foreign keys
 | 
	
		
			
				|  |  | +  // followed.
 | 
	
		
			
				|  |  |    foreach ($values as $field => $value) {
 | 
	
		
			
				|  |  | -    // make sure the field is in the table description. If not then return an error
 | 
	
		
			
				|  |  | -    // message
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Require the field be in the table description.
 | 
	
		
			
				|  |  |      if (!array_key_exists($field, $table_desc['fields'])) {
 | 
	
		
			
				|  |  |        tripal_report_error('tripal_core', TRIPAL_ERROR,
 | 
	
		
			
				|  |  |          'chado_select_record: The field "%field" does not exist for the table "%table".  Cannot perform query. Values: %array',
 | 
	
	
		
			
				|  | @@ -1141,47 +1166,129 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      $select[] = $field;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // CASE 1: We have an array for a value.
 | 
	
		
			
				|  |  |      if (is_array($value)) {
 | 
	
		
			
				|  |  | -      // if the user has specified multiple values for matching then this we
 | 
	
		
			
				|  |  | -      // want to catch that and save them in our $where array, otherwise
 | 
	
		
			
				|  |  | -      // we'll descend for a foreign key relationship
 | 
	
		
			
				|  |  | -      if (array_values($value) === $value) {
 | 
	
		
			
				|  |  | -        $where[$field] = $value;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // CASE 1a: If there is only one element in the array, treat it the same
 | 
	
		
			
				|  |  | +      // as a non-array value.
 | 
	
		
			
				|  |  | +      if (count($value) == 1 AND is_int(key($value))) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        $value = array_pop($value);
 | 
	
		
			
				|  |  | +        $op = '=';
 | 
	
		
			
				|  |  | +        chado_select_record_check_value_type($op, $value, $table_desc['fields'][$field]['type']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        $where[] = array(
 | 
	
		
			
				|  |  | +          'field' => $field,
 | 
	
		
			
				|  |  | +          'op' => $op,
 | 
	
		
			
				|  |  | +          'data' => $value
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      else {
 | 
	
		
			
				|  |  | -        // select the value from the foreign key relationship for this value
 | 
	
		
			
				|  |  | -        $foreign_options = array(
 | 
	
		
			
				|  |  | -          'regex_columns' => $options['regex_columns'],
 | 
	
		
			
				|  |  | +      // CASE 1b: If there is a 'data' key in the array then we have the new
 | 
	
		
			
				|  |  | +      // complex filtering format with a single criteria.
 | 
	
		
			
				|  |  | +      elseif (isset($value['data']) AND isset($value['op'])) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        $value['field'] = $field;
 | 
	
		
			
				|  |  | +        $where[] = $value;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // CASE 1c: If we have an integer indexed array and the first element is
 | 
	
		
			
				|  |  | +      // not an array then we have a simple array of values to be used for an IN clause.
 | 
	
		
			
				|  |  | +      elseif (is_int(key($value)) AND !is_array(current($value))) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        $where[] = array(
 | 
	
		
			
				|  |  | +          'field' => $field,
 | 
	
		
			
				|  |  | +          'op' => 'IN',
 | 
	
		
			
				|  |  | +          'data' => $value
 | 
	
		
			
				|  |  |          );
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // We have a multi-dimensional array: 2 cases...
 | 
	
		
			
				|  |  | +      else {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // CASE 1d: If there is a multi-dimensional array with each sub-array
 | 
	
		
			
				|  |  | +        // containing a data key then we have the new complex filtering format
 | 
	
		
			
				|  |  | +        // with multiple criteria.
 | 
	
		
			
				|  |  | +        if (isset($value[0]['data']) AND isset($value[0]['op'])) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        $results = chado_schema_get_foreign_key($table_desc, $field, $value, $foreign_options);
 | 
	
		
			
				|  |  | -        if (!$results or count($results)==0) {
 | 
	
		
			
				|  |  | -          return array();
 | 
	
		
			
				|  |  | +          foreach ($value as $subvalue) {
 | 
	
		
			
				|  |  | +            $subvalue['field'] = $field;
 | 
	
		
			
				|  |  | +            $where[] = $subvalue;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        // CASE 1e: We have a multi-dimensional array that doesn't fit any of the
 | 
	
		
			
				|  |  | +        // above cases then we have a foreign key definition to follow.
 | 
	
		
			
				|  |  |          else {
 | 
	
		
			
				|  |  | -          $where[$field] = $results;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Select the value from the foreign key relationship for this value.
 | 
	
		
			
				|  |  | +          $foreign_options = array(
 | 
	
		
			
				|  |  | +            'regex_columns' => $options['regex_columns'],
 | 
	
		
			
				|  |  | +          );
 | 
	
		
			
				|  |  | +          $results = chado_schema_get_foreign_key($table_desc, $field, $value, $foreign_options);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Ensure that looking up the foreign key didn't fail in an error.
 | 
	
		
			
				|  |  | +          if ($results === FALSE OR $results === NULL) {
 | 
	
		
			
				|  |  | +            tripal_report_error('tripal_core', TRIPAL_ERROR,
 | 
	
		
			
				|  |  | +              'chado_select_record: could not follow the foreign key definition
 | 
	
		
			
				|  |  | +              for %field where the definition supplied was %value',
 | 
	
		
			
				|  |  | +              array('%field' => $field, '%value' => print_r($value, TRUE))
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          // Ensure that there were results returned.
 | 
	
		
			
				|  |  | +          elseif (count($results)==0) {
 | 
	
		
			
				|  |  | +            tripal_report_error('tripal_core', TRIPAL_ERROR,
 | 
	
		
			
				|  |  | +              'chado_select_record: the foreign key definition for %field
 | 
	
		
			
				|  |  | +              returned no results where the definition supplied was %value',
 | 
	
		
			
				|  |  | +              array('%field' => $field, '%value' => print_r($value, TRUE))
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          // If there was only a single resutlt then add it using an op of =.
 | 
	
		
			
				|  |  | +          elseif (count($results) == 1) {
 | 
	
		
			
				|  |  | +            $results = array_pop($results);
 | 
	
		
			
				|  |  | +            $op = '=';
 | 
	
		
			
				|  |  | +            chado_select_record_check_value_type($op, $results, $table_desc['fields'][$field]['type']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            $where[] = array(
 | 
	
		
			
				|  |  | +              'field' => $field,
 | 
	
		
			
				|  |  | +              'op' => $op,
 | 
	
		
			
				|  |  | +              'data' => $results
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          // Otherwise multiple results were returned so we want to form an
 | 
	
		
			
				|  |  | +          // IN (x, y, z) expression.
 | 
	
		
			
				|  |  | +          else {
 | 
	
		
			
				|  |  | +            $where[] = array(
 | 
	
		
			
				|  |  | +              'field' => $field,
 | 
	
		
			
				|  |  | +              'op' => 'IN',
 | 
	
		
			
				|  |  | +              'data' => $results
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    // CASE 2: We have a single value.
 | 
	
		
			
				|  |  |      else {
 | 
	
		
			
				|  |  | -      // need to catch a 0 and make int if integer field
 | 
	
		
			
				|  |  | -      // but we don't want to catch a NULL
 | 
	
		
			
				|  |  | -      if ($value === NULL) {
 | 
	
		
			
				|  |  | -        $where[$field] = NULL;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      elseif ($table_desc['fields'][$field]['type'] == 'int') {
 | 
	
		
			
				|  |  | -        $where[$field][] = (int) $value;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      else {
 | 
	
		
			
				|  |  | -        $where[$field][] = $value;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      $op = '=';
 | 
	
		
			
				|  |  | +      chado_select_record_check_value_type($op, $value, $table_desc['fields'][$field]['type']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      $where[] = array(
 | 
	
		
			
				|  |  | +        'field' => $field,
 | 
	
		
			
				|  |  | +        'op' => $op,
 | 
	
		
			
				|  |  | +        'data' => $value
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Support Deprecated method for regex conditions.
 | 
	
		
			
				|  |  | +    $current_key = key($where);
 | 
	
		
			
				|  |  | +    if (in_array($field, $options['regex_columns'])) {
 | 
	
		
			
				|  |  | +      $where[$current_key]['op'] = '~*';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // now build the SQL 
 | 
	
		
			
				|  |  | +  // Now build the SQL.
 | 
	
		
			
				|  |  |    if (empty($where)) {
 | 
	
		
			
				|  |  | -    // sometimes want to select everything
 | 
	
		
			
				|  |  | +    // Sometimes want to select everything.
 | 
	
		
			
				|  |  |      $sql  = "SELECT " . implode(', ', $columns) . " ";
 | 
	
		
			
				|  |  |      $sql .= 'FROM {' . $table . '} ';
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -1189,50 +1296,50 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      $sql  = "SELECT " . implode(', ', $columns) . " ";
 | 
	
		
			
				|  |  |      $sql .= 'FROM {' . $table . '} ';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // if $values is empty then we want all results so no where clause
 | 
	
		
			
				|  |  | +    // If $values is empty then we want all results so no where clause.
 | 
	
		
			
				|  |  |      if (!empty($values)) {
 | 
	
		
			
				|  |  |        $sql .= "WHERE ";
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    foreach ($where as $field => $value) {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // if we have multiple values returned then we need an 'IN' statement
 | 
	
		
			
				|  |  | -      // in our where statement
 | 
	
		
			
				|  |  | -      if (count($value) > 1) {
 | 
	
		
			
				|  |  | -        $sql .= "$field IN (";
 | 
	
		
			
				|  |  | -        $index = 0;
 | 
	
		
			
				|  |  | -        foreach ($value as $v) {
 | 
	
		
			
				|  |  | -          $sql .= ":$field" . $index . ', ';
 | 
	
		
			
				|  |  | -          $args[":$field" . $index] = $v;
 | 
	
		
			
				|  |  | -          $index++;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        $sql = drupal_substr($sql, 0, -2); // remove trailing ', '
 | 
	
		
			
				|  |  | -        $sql .= ") AND ";
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      // if we have a null value then we need an IS NULL in our where statement
 | 
	
		
			
				|  |  | -      elseif ($value === NULL) {
 | 
	
		
			
				|  |  | -        $sql .= "$field IS NULL AND ";
 | 
	
		
			
				|  |  | -        // Need to remove one from the argument count b/c nulls don't add an argument
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      // if we have a single value then we need an = in our where statement
 | 
	
		
			
				|  |  | -      else {
 | 
	
		
			
				|  |  | -        $operator = '=';
 | 
	
		
			
				|  |  | -        if (in_array($field, $options['regex_columns'])) {
 | 
	
		
			
				|  |  | -          $operator = '~*';
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (in_array($field, $options['case_insensitive_columns'])) {
 | 
	
		
			
				|  |  | -          $sql .= "lower($field) $operator lower(:$field) AND ";
 | 
	
		
			
				|  |  | -          $args[":$field"] = $value[0];
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        else {
 | 
	
		
			
				|  |  | -          $sql .= "$field $operator :$field AND ";
 | 
	
		
			
				|  |  | -          $args[":$field"] = $value[0];
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    foreach ($where as $clause_num => $value_def) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      switch ($value_def['op']) {
 | 
	
		
			
				|  |  | +        // Deal with 'field IN (x, y, z)' where clauses.
 | 
	
		
			
				|  |  | +        case 'IN':
 | 
	
		
			
				|  |  | +          $sql .= $value_def['field'] . " IN (";
 | 
	
		
			
				|  |  | +          $index = 0;
 | 
	
		
			
				|  |  | +          foreach ($value_def['data'] as $v) {
 | 
	
		
			
				|  |  | +            $placeholder = ':' . $value_def['field'] . $clause_num .'_' . $index;
 | 
	
		
			
				|  |  | +            $sql .= $placeholder . ', ';
 | 
	
		
			
				|  |  | +            $args[$placeholder] = $v;
 | 
	
		
			
				|  |  | +            $index++;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          $sql = drupal_substr($sql, 0, -2); // remove trailing ', '
 | 
	
		
			
				|  |  | +          $sql .= ") AND ";
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Deal with IS NULL.
 | 
	
		
			
				|  |  | +        case 'IS NULL':
 | 
	
		
			
				|  |  | +          $sql .= $value_def['field'] . ' IS NULL AND ';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Default is [field] [op] [data].
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          $placeholder = ':'. $value_def['field'] . $clause_num;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Support case insensitive columns.
 | 
	
		
			
				|  |  | +          if (in_array($value_def['field'], $options['case_insensitive_columns'])) {
 | 
	
		
			
				|  |  | +            $sql .= 'lower(' . $value_def['field'] .') '. $value_def['op'] .' lower('. $placeholder . ') AND ';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          else {
 | 
	
		
			
				|  |  | +            $sql .= $value_def['field'] .' '. $value_def['op'] .' '. $placeholder . ' AND ';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          $args[$placeholder] = $value_def['data'];
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    } // end foreach item in where clause
 | 
	
		
			
				|  |  | +    } // end foreach item in where clause.
 | 
	
		
			
				|  |  |      $sql = drupal_substr($sql, 0, -4);  // get rid of the trailing 'AND '
 | 
	
		
			
				|  |  |    } // end if (empty($where)){ } else {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // finally add any ordering of the results to the SQL statement
 | 
	
		
			
				|  |  | +  // Finally add any ordering of the results to the SQL statement.
 | 
	
		
			
				|  |  |    if (count($options['order_by']) > 0) {
 | 
	
		
			
				|  |  |      $sql .= " ORDER BY ";
 | 
	
		
			
				|  |  |      foreach ($options['order_by'] as $field => $dir) {
 | 
	
	
		
			
				|  | @@ -1241,7 +1348,7 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      $sql = drupal_substr($sql, 0, -2);  // get rid of the trailing ', '
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // if the caller has requested the SQL rather than the results then do so
 | 
	
		
			
				|  |  | +  // if the caller has requested the SQL rather than the results then do so.
 | 
	
		
			
				|  |  |    if ($options['return_sql'] == TRUE) {
 | 
	
		
			
				|  |  |      return array('sql' => $sql, 'args' => $args);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -1253,7 +1360,11 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |      $resource = chado_query($sql, $args);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // format results into an array
 | 
	
		
			
				|  |  | +dpm($sql, 'sql');
 | 
	
		
			
				|  |  | +dpm($args, 'args');
 | 
	
		
			
				|  |  | +dpm($where, 'where');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Format results into an array.
 | 
	
		
			
				|  |  |    $results = array();
 | 
	
		
			
				|  |  |    foreach ($resource as $r) {
 | 
	
		
			
				|  |  |      $results[] = $r;
 | 
	
	
		
			
				|  | @@ -1261,9 +1372,48 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
 | 
	
		
			
				|  |  |    if ($options['has_record']) {
 | 
	
		
			
				|  |  |      return count($results);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    return $results;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Helper Function: check that the value is the correct type.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * This function is used by chado_select_record() when building the $where
 | 
	
		
			
				|  |  | + * clause array to ensure that any single values are the correct type based
 | 
	
		
			
				|  |  | + * on the table definition. Furthermore, it ensures that NULL's are caught
 | 
	
		
			
				|  |  | + * changing the operator to 'IS NULL'.
 | 
	
		
			
				|  |  | + * @code
 | 
	
		
			
				|  |  | +      $op = '=';
 | 
	
		
			
				|  |  | +      chado_select_record_check_value_type($op, $value, $table_desc['fields'][$field]['type']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      $where[] = array(
 | 
	
		
			
				|  |  | +        'field' => $field,
 | 
	
		
			
				|  |  | +        'op' => $op,
 | 
	
		
			
				|  |  | +        'data' => $value
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | + * @endcode
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * @param $op
 | 
	
		
			
				|  |  | + *   The operator being used. This is mostly passed in to allow it to be changed
 | 
	
		
			
				|  |  | + *   if a NULL value is detected.
 | 
	
		
			
				|  |  | + * @param $value
 | 
	
		
			
				|  |  | + *   The value to be checked and adjusted.
 | 
	
		
			
				|  |  | + * @param $type
 | 
	
		
			
				|  |  | + *   The type from the table definition that's used to determine the type of
 | 
	
		
			
				|  |  | + *   value.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function chado_select_record_check_value_type(&$op, &$value, $type) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if ($value === NULL) {
 | 
	
		
			
				|  |  | +    $op = 'IS NULL';
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  elseif ($type == 'int') {
 | 
	
		
			
				|  |  | +    $value = (int) $value;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Use this function instead of db_query() to avoid switching databases
 | 
	
		
			
				|  |  |   * when making query to the chado database
 | 
	
	
		
			
				|  | @@ -1392,16 +1542,16 @@ function chado_pager_query($query, $args, $limit, $element, $count_query = '') {
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * A function to retrieve the total number of records for a pager that
 | 
	
		
			
				|  |  |   * was generated using the chado_pager_query() function
 | 
	
		
			
				|  |  | - * 
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   * @param $element
 | 
	
		
			
				|  |  |   *   The $element argument that was passed to the chado_pager_query function
 | 
	
		
			
				|  |  | - *   
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  |   * @ingroup tripal_chado_query_api
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  function chado_pager_get_count($element) {
 | 
	
		
			
				|  |  |    $q = $_GET['q'];
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -  if (array_key_exists($q, $GLOBALS['chado_pager']) and 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  if (array_key_exists($q, $GLOBALS['chado_pager']) and
 | 
	
		
			
				|  |  |        array_key_exists($element, $GLOBALS['chado_pager'][$q])) {
 | 
	
		
			
				|  |  |      return $GLOBALS['chado_pager'][$q][$element]['total_records'];
 | 
	
		
			
				|  |  |    }
 |