Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.859
diff -u -p -r1.859 common.inc
--- includes/common.inc	28 Jan 2009 07:43:26 -0000	1.859
+++ includes/common.inc	29 Jan 2009 00:50:42 -0000
@@ -3904,6 +3904,119 @@ function drupal_write_record($table, &$o
 }
 
 /**
+ * Load one or more records from the database based upon the schema.
+ *
+ * @param $table
+ *   The name of the table; this must exist in schema API.
+ * @param $alias
+ *   An alias for the table.
+ * @param $conditions
+ *   An array of conditions to apply to the query.
+ * @param $fields
+ *   Array: the names of the fields to be returned. If empty, all fields will be
+ *   returned.
+ * @return
+ *   If all primary keys are sent as conditions, a single record object.
+ *   Otherwise, an array of all matching records. False on failure.
+ */
+function drupal_read_records($table, $alias = NULL, $conditions = array(), $fields = array(), $alter = TRUE) {
+  $schema = drupal_get_schema($table);
+  if (empty($schema)) {
+    return FALSE;
+  }
+
+  // If no fields were specified, use all fields.
+  if (empty($fields)) {
+    $fields = array_keys($schema['fields']);
+  }
+
+  // If no alias was specified, use the full table name.
+  // If no fields were specified, use all fields.
+  if (empty($alias)) {
+    $alias = $table;
+  }
+
+  $primary_keys = $schema['primary key'];
+
+  // Accept a numeric ID key.
+  if (is_numeric($conditions)) {
+    if (count($primary_keys) > 1) {
+      return FALSE;
+    }
+    $conditions = array($primary_keys[0], $conditions);
+    // Since we have a requested ID, we're loading a single record.
+    $fetch_all = FALSE;
+  }
+  // If we have conditions for all primary keys, we may be loading a single
+  // record.
+  elseif (count(array_intersect($primary_keys, array_keys($conditions))) == count($primary_keys)) {
+    $fetch_all = FALSE;
+    // If any primary key is set as a full condition with a comparison
+    // operator (e.g., '<'), we might get multiple rows.
+    foreach ($primary_keys as $key) {
+      if (is_array($conditions[$key])) {
+        $fetch_all = TRUE;
+        break;
+      }
+    }
+  }
+  else {
+    $fetch_all = TRUE;
+  }
+  $query = db_select($table, $alias);
+  $query->fields($alias, $fields);
+  foreach ($conditions as $field => $condition) {
+    // Comparison operator parameters are passed in array format.
+    if (is_array($condition)) {
+      $query->condition($field, $condition['value'], $condition['operator']);
+    }
+    // If not an array, this is a simple value with the default '=' parameter.
+    else {
+      $query->condition($field, $condition, '=');
+    }
+  }
+
+  if ($fetch_all) {
+    $result = $query->execute()->fetchAll();
+    if (empty($result)) {
+      return FALSE;
+    }
+    foreach (array_keys($result) as $key) {
+      // Send the results for altering if requested.
+      if ($alter) {
+        drupal_alter('drupal_read_records', $result[$key], $table);
+      }
+      // Iterate through result records.
+      foreach ($result[$key] as $field => $value) {
+        // If required, unserialize results
+        if (isset($schema['fields'][$field]) && !empty($schema['fields'][$field]['serialize'])) {
+          $result[$key]->$field = unserialize($value);
+        }
+      }
+
+    }
+  }
+  else {
+    $result = $query->execute()->fetch();
+    if (empty($result)) {
+      return FALSE;
+    }
+    // Send the results for altering if requested.
+    if ($alter) {
+      drupal_alter('drupal_read_records', $result, $table);
+    }
+    foreach ($result as $field => $value) {
+      if (isset($schema['fields'][$field]) && !empty($schema['fields'][$field]['serialize'])) {
+        $result->$field = unserialize($value);
+      }
+    }
+
+  }
+
+  return $result;
+}
+
+/**
  * @} End of "ingroup schemaapi".
  */
 
