Commit cc421475 authored by Dries's avatar Dries

- Patch #603236 by bjaspan, catch: add count facility to field_attach_query()....

- Patch #603236 by bjaspan, catch: add count facility to field_attach_query(). Was ready before code freeze.
parent 77471032
......@@ -1064,15 +1064,8 @@ function hook_field_attach_pre_update($obj_type, $object, &$skip_fields) {
* A storage module that doesn't support querying a given column should raise
* a FieldQueryException. Incompatibilities should be mentioned on the module
* project page.
* @param $count
* See field_attach_query().
* @param $cursor
* See field_attach_query().
* @param $age
* - FIELD_LOAD_CURRENT: query the most recent revisions for all
* objects. The results will be keyed by object type and object id.
* - FIELD_LOAD_REVISION: query all revisions. The results will be keyed by
* object type and object revision id.
* @param $options
* See field_attach_query(). All option keys are guaranteed to be specified.
* @param $skip_field
* Boolean, always coming as FALSE.
* @return
......@@ -1080,7 +1073,7 @@ function hook_field_attach_pre_update($obj_type, $object, &$skip_fields) {
* The $skip_field parameter should be set to TRUE if the query has been
* handled.
*/
function hook_field_attach_pre_query($field_name, $conditions, $count, &$cursor = NULL, $age, &$skip_field) {
function hook_field_attach_pre_query($field_name, $conditions, $options, &$skip_field) {
}
/**
......@@ -1331,16 +1324,12 @@ function hook_field_storage_delete_revision($obj_type, $object, $fields) {
* A storage module that doesn't support querying a given column should raise
* a FieldQueryException. Incompatibilities should be mentioned on the module
* project page.
* @param $count
* See field_attach_query().
* @param $cursor
* See field_attach_query().
* @param $age
* See field_attach_query().
* @param $options
* See field_attach_query(). All option keys are guaranteed to be specified.
* @return
* See field_attach_query().
*/
function hook_field_storage_query($field_name, $conditions, $count, &$cursor = NULL, $age) {
function hook_field_storage_query($field_name, $conditions, $options) {
}
/**
......
......@@ -1026,26 +1026,28 @@ function field_attach_delete_revision($obj_type, $object) {
* array('value', 12, '>'),
* );
* @endcode
* @param $count
* The number of results that is requested. This is only a
* @param $options
* An associative array of additional options:
* - limit: The number of results that is requested. This is only a
* hint to the storage engine(s); callers should be prepared to
* handle fewer or more results. Specify FIELD_QUERY_NO_LIMIT to retrieve
* all available objects. This parameter has no default value so
* all available objects. This option has a default value of 0 so
* callers must make an explicit choice to potentially retrieve an
* enormous result set.
* @param &$cursor
* An opaque cursor that allows a caller to iterate through multiple
* result sets. On the first call, pass 0; the correct value to pass
* on the next call will be written into $cursor on return. When
* there is no more query data available, $cursor will be filled in
* with FIELD_QUERY_COMPLETE. If $cursor is passed as NULL,
* the first result set is returned and no next cursor is returned.
* @param $age
* Internal use only. Use field_attach_query_revisions() instead of passing
* FIELD_LOAD_REVISION.
* - FIELD_LOAD_CURRENT (default): query the most recent revisions for all
* - cursor: A reference to an opaque cursor that allows a caller to
* iterate through multiple result sets. On the first call, pass 0;
* the correct value to pass on the next call will be written into
* the value on return. When there is no more query data available,
* the value will be filled in with FIELD_QUERY_COMPLETE. If cursor
* is passed as NULL, the first result set is returned and no next
* cursor is returned.
* - count: If TRUE, return a single count of all matching objects;
* limit and cursor are ignored.
* - age: Internal use only. Use field_attach_query_revisions()
* instead of passing FIELD_LOAD_REVISION.
* - FIELD_LOAD_CURRENT (default): query the most recent revisions for all
* objects. The results will be keyed by object type and object id.
* - FIELD_LOAD_REVISION: query all revisions. The results will be keyed by
* - FIELD_LOAD_REVISION: query all revisions. The results will be keyed by
* object type and object revision id.
* @return
* An array keyed by object type (e.g. 'node', 'user'...), then by object id
......@@ -1056,17 +1058,22 @@ function field_attach_delete_revision($obj_type, $object) {
* Throws a FieldQueryException if the field's storage doesn't support the
* specified conditions.
*/
function field_attach_query($field_id, $conditions, $count, &$cursor = NULL, $age = FIELD_LOAD_CURRENT) {
if (!isset($cursor)) {
$cursor = 0;
}
function field_attach_query($field_id, $conditions, $options = array()) {
// Merge in default options.
$default_options = array(
'limit' => 0,
'cursor' => 0,
'count' => FALSE,
'age' => FIELD_LOAD_CURRENT,
);
$options += $default_options;
// Give a chance to 3rd party modules that bypass the storage engine to
// handle the query.
$skip_field = FALSE;
foreach (module_implements('field_attach_pre_query') as $module) {
$function = $module . '_field_attach_pre_query';
$results = $function($field_id, $conditions, $count, $cursor, $age, $skip_field);
$results = $function($field_id, $conditions, $options, $skip_field);
// Stop as soon as a module claims it handled the query.
if ($skip_field) {
break;
......@@ -1076,7 +1083,7 @@ function field_attach_query($field_id, $conditions, $count, &$cursor = NULL, $ag
if (!$skip_field) {
$field = field_info_field_by_id($field_id);
$function = $field['storage']['module'] . '_field_storage_query';
$results = $function($field_id, $conditions, $count, $cursor, $age);
$results = $function($field_id, $conditions, $options);
}
return $results;
......@@ -1091,22 +1098,14 @@ function field_attach_query($field_id, $conditions, $count, &$cursor = NULL, $ag
* The id of the field to query.
* @param $conditions
* See field_attach_query().
* @param $count
* The number of results that is requested. This is only a
* hint to the storage engine(s); callers should be prepared to
* handle fewer or more results. Specify FIELD_QUERY_NO_LIMIT to retrieve
* all available objects. This parameter has no default value so
* callers must make an explicit choice to potentially retrieve an
* enormous result set.
* @param &$cursor
* An opaque cursor that allows a caller to iterate through multiple
* result sets. On the first call, pass 0; the correct value to pass
* on the next call will be written into $cursor on return.
* @param $options
* An associative array of additional options. See field_attach_query().
* @return
* See field_attach_query().
*/
function field_attach_query_revisions($field_id, $conditions, $count, &$cursor = NULL) {
return field_attach_query($field_id, $conditions, $count, $cursor, FIELD_LOAD_REVISION);
function field_attach_query_revisions($field_id, $conditions, $options = array()) {
$options['age'] = FIELD_LOAD_REVISION;
return field_attach_query($field_id, $conditions, $options);
}
/**
......
......@@ -965,7 +965,7 @@ function field_purge_batch($batch_size) {
$field = field_info_field_by_id($instance['field_id']);
// Retrieve some pseudo-objects.
$obj_types = field_attach_query($instance['field_id'], array(array('bundle', $instance['bundle']), array('deleted', 1)), $batch_size);
$obj_types = field_attach_query($instance['field_id'], array(array('bundle', $instance['bundle']), array('deleted', 1)), array('limit' => $batch_size));
if (count($obj_types) > 0) {
// Field data for the instance still exists.
......
......@@ -615,7 +615,7 @@ function field_view_field($obj_type, $object, $field, $instance, $build_mode = '
* TRUE if the field has data for any object; FALSE otherwise.
*/
function field_has_data($field) {
$results = field_attach_query($field['id'], array(), 1);
$results = field_attach_query($field['id'], array(), array('limit' => 1));
return !empty($results);
}
......
This diff is collapsed.
......@@ -469,8 +469,8 @@ function field_sql_storage_field_storage_purge($obj_type, $object, $field, $inst
/**
* Implement hook_field_storage_query().
*/
function field_sql_storage_field_storage_query($field_id, $conditions, $count, &$cursor, $age) {
$load_current = $age == FIELD_LOAD_CURRENT;
function field_sql_storage_field_storage_query($field_id, $conditions, $options) {
$load_current = $options['age'] == FIELD_LOAD_CURRENT;
$field = field_info_field_by_id($field_id);
$field_name = $field['field_name'];
......@@ -481,14 +481,6 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $count, &
$query = db_select($table, 't');
$query->join('field_config_entity_type', 'e', 't.etid = e.etid');
$query
->fields('t', array('bundle', 'entity_id', 'revision_id'))
->fields('e', array('type'))
// We need to ensure objects arrive in a consistent order for the
// range() operation to work.
->orderBy('t.etid')
->orderBy('t.entity_id');
// Add conditions.
foreach ($conditions as $condition) {
// A condition is either a (column, value, operator) triple, or a
......@@ -542,6 +534,21 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $count, &
$query->condition('deleted', 0);
}
// For a count query, return the count now.
if ($options['count']) {
$query->addExpression('COUNT(DISTINCT e.type,t.entity_id,t.revision_id)');
return $query->execute()->fetchField();
}
// For a data query, add fields.
$query
->fields('t', array('bundle', 'entity_id', 'revision_id'))
->fields('e', array('type'))
// We need to ensure objects arrive in a consistent order for the
// range() operation to work.
->orderBy('t.etid')
->orderBy('t.entity_id');
// Initialize results array
$return = array();
......@@ -551,15 +558,15 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $count, &
// less rows than asked for.
$obj_count = 0;
do {
if ($count != FIELD_QUERY_NO_LIMIT) {
$query->range($cursor, $count);
if ($options['limit'] != FIELD_QUERY_NO_LIMIT) {
$query->range($options['cursor'], $options['limit']);
}
$results = $query->execute();
$row_count = 0;
foreach ($results as $row) {
$row_count++;
$cursor++;
$options['cursor']++;
// If querying all revisions and the entity type has revisions, we need
// to key the results by revision_ids.
$entity_type = field_info_fieldable_types($row->type);
......@@ -570,12 +577,12 @@ function field_sql_storage_field_storage_query($field_id, $conditions, $count, &
$obj_count++;
}
}
} while ($count != FIELD_QUERY_NO_LIMIT && $row_count == $count && $obj_count < $count);
} while ($options['limit'] != FIELD_QUERY_NO_LIMIT && $row_count == $options['limit'] && $obj_count < $options['limit']);
// The query is complete when the last batch returns less rows than asked
// for.
if ($row_count < $count) {
$cursor = FIELD_QUERY_COMPLETE;
if ($row_count < $options['limit']) {
$options['cursor'] = FIELD_QUERY_COMPLETE;
}
return $return;
......
......@@ -921,7 +921,7 @@ function file_get_file_references($file, $field = NULL, $age = FIELD_LOAD_REVISI
if (!isset($references[$field_name])) {
// Get each time this file is used within a field.
$cursor = 0;
$references[$field_name] = field_attach_query($file_field['id'], array(array('fid', $file->fid)), FIELD_QUERY_NO_LIMIT, $cursor, $age);
$references[$field_name] = field_attach_query($file_field['id'], array(array('fid', $file->fid)), array('limit' => FIELD_QUERY_NO_LIMIT, 'cursor' => &$cursor, 'age'=> $age));
}
}
......
......@@ -1200,7 +1200,7 @@ function _taxonomy_clean_field_cache($term) {
if ($obj_types) {
$conditions[] = array('type', $obj_types, 'NOT IN');
}
$results = field_attach_query($field['id'], $conditions, FIELD_QUERY_NO_LIMIT);
$results = field_attach_query($field['id'], $conditions, array('limit' => FIELD_QUERY_NO_LIMIT));
foreach ($results as $obj_type => $objects) {
foreach (array_keys($objects) as $id) {
$cids[] = "field:$obj_type:$id";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment