- Patch #423888 by mikeryan, Crell, drunken monkey: use subqueries for ->countQuery(), at least for MySQL.
parent
a9c9ef2d30
commit
66d31c52ba
|
@ -93,6 +93,24 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn
|
|||
*/
|
||||
public function &getOrderBy();
|
||||
|
||||
/**
|
||||
* Returns a reference to the group-by array for this query.
|
||||
*
|
||||
* Because this method returns by reference, alter hooks may edit the group-by
|
||||
* array directly to make their changes. If just adding additional grouping
|
||||
* fields, however, the use of groupBy() is preferred.
|
||||
*
|
||||
* Note that this method must be called by reference as well:
|
||||
*
|
||||
* @code
|
||||
* $fields =& $query->getGroupBy();
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* A reference to the group-by array structure.
|
||||
*/
|
||||
public function &getGroupBy();
|
||||
|
||||
/**
|
||||
* Returns a reference to the tables array for this query.
|
||||
*
|
||||
|
@ -619,6 +637,10 @@ class SelectQueryExtender implements SelectQueryInterface {
|
|||
return $this->query->getOrderBy();
|
||||
}
|
||||
|
||||
public function &getGroupBy() {
|
||||
return $this->query->getGroupBy();
|
||||
}
|
||||
|
||||
public function &getTables() {
|
||||
return $this->query->getTables();
|
||||
}
|
||||
|
@ -1026,6 +1048,10 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
|||
return $this->order;
|
||||
}
|
||||
|
||||
public function &getGroupBy() {
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function &getTables() {
|
||||
return $this->tables;
|
||||
}
|
||||
|
@ -1279,13 +1305,24 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
|||
// Create our new query object that we will mutate into a count query.
|
||||
$count = clone($this);
|
||||
|
||||
$group_by = array_keys($count->getGroupBy());
|
||||
|
||||
if (!$count->distinct) {
|
||||
// When not executing a distinct query, we can zero-out existing fields
|
||||
// and expressions.
|
||||
// and expressions that are not used by a GROUP BY. Fields listed in
|
||||
// the GROUP BY clause need to be present in the query.
|
||||
$fields =& $count->getFields();
|
||||
$fields = array();
|
||||
foreach (array_keys($fields) as $field) {
|
||||
if (!empty($group_by[$field])) {
|
||||
unset($fields[$field]);
|
||||
}
|
||||
}
|
||||
$expressions =& $count->getExpressions();
|
||||
$expressions = array();
|
||||
foreach (array_keys($expressions) as $field) {
|
||||
if (!empty($group_by[$field])) {
|
||||
unset($fields[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove 'all_fields' statements, which are expanded into tablename.*
|
||||
// when the query is executed.
|
||||
|
@ -1294,22 +1331,25 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
|||
}
|
||||
}
|
||||
|
||||
// If we've just removed all fields from the query, make sure there is at
|
||||
// least one so that the query still runs.
|
||||
$count->addExpression('1');
|
||||
|
||||
// Ordering a count query is a waste of cycles, and breaks on some
|
||||
// databases anyway.
|
||||
$orders = &$count->getOrderBy();
|
||||
$orders = array();
|
||||
|
||||
if ($count->distinct) {
|
||||
// If the query is distinct, we need to execute it in a subquery,
|
||||
// because SQL99 does not support counting on distinct multiple fields.
|
||||
$count = db_select($count);
|
||||
if ($count->distinct && !empty($group_by)) {
|
||||
// If the query is distinct and contains a GROUP BY, we need to remove the
|
||||
// distinct because SQL99 does not support counting on distinct multiple fields.
|
||||
$count->distinct = FALSE;
|
||||
}
|
||||
|
||||
// COUNT() is an expression, so we add that back in.
|
||||
$count->addExpression('COUNT(*)');
|
||||
$query = db_select($count);
|
||||
$query->addExpression('COUNT(*)');
|
||||
|
||||
return $count;
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
|
|
|
@ -216,10 +216,11 @@ function field_language($entity_type, $entity, $field_name = NULL, $langcode = N
|
|||
if (!isset($display_languages[$entity_type][$id][$langcode])) {
|
||||
$display_language = array();
|
||||
|
||||
// By default display language is set to LANGUAGE_NONE. It is up to
|
||||
// translation handlers to implement language fallback rules.
|
||||
// By default display language is set to LANGUAGE_NONE if the field
|
||||
// translation is not available. It is up to translation handlers to
|
||||
// implement language fallback rules.
|
||||
foreach (field_info_instances($entity_type, $bundle) as $instance) {
|
||||
$display_language[$instance['field_name']] = LANGUAGE_NONE;
|
||||
$display_language[$instance['field_name']] = isset($entity->{$instance['field_name']}[$langcode]) ? $langcode : LANGUAGE_NONE;
|
||||
}
|
||||
|
||||
if (field_has_translation_handler($entity_type)) {
|
||||
|
|
|
@ -2639,8 +2639,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
|
|||
field_create_instance($instance);
|
||||
|
||||
$entity = field_test_create_stub_entity(1, 1, $this->instance['bundle']);
|
||||
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
$instances = field_info_instances($entity_type, $bundle);
|
||||
$instances = field_info_instances($entity_type, $this->instance['bundle']);
|
||||
|
||||
$enabled_languages = field_content_languages();
|
||||
$languages = array();
|
||||
|
@ -2688,6 +2687,13 @@ class FieldTranslationsTestCase extends FieldTestCase {
|
|||
drupal_static_reset('field_language');
|
||||
$langcode = field_language($entity_type, $entity, $this->field_name, $requested_language);
|
||||
$this->assertTrue(isset($entity->{$this->field_name}[$langcode]) && $langcode != $requested_language, t('The display language for the (single) field %field_name is %language.', array('%field_name' => $field_name, '%language' => $langcode)));
|
||||
|
||||
// Test field_language() basic behavior without language fallback.
|
||||
variable_set('field_test_language_fallback', FALSE);
|
||||
$entity->{$this->field_name}[$requested_language] = mt_rand(1, 127);
|
||||
drupal_static_reset('field_language');
|
||||
$display_language = field_language($entity_type, $entity, $this->field_name, $requested_language);
|
||||
$this->assertEqual($display_language, $requested_language, t('Display language behave correctly when language fallback is disabled'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,7 +103,9 @@ function field_test_field_available_languages_alter(&$languages, $context) {
|
|||
* Implements hook_field_language_alter().
|
||||
*/
|
||||
function field_test_field_language_alter(&$display_language, $context) {
|
||||
locale_field_language_fallback($display_language, $context['entity'], $context['language']);
|
||||
if (variable_get('field_test_language_fallback', TRUE)) {
|
||||
locale_field_language_fallback($display_language, $context['entity'], $context['language']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1986,6 +1986,19 @@ class DatabaseSelectComplexTestCase extends DatabaseTestCase {
|
|||
$this->assertEqual($count, 6, t('Counted the correct number of records.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can generate a count query from a query with GROUP BY.
|
||||
*/
|
||||
function testCountQueryGroupBy() {
|
||||
$query = db_select('test_task');
|
||||
$pid_field = $query->addField('test_task', 'pid');
|
||||
$query->groupBy('pid');
|
||||
|
||||
$count = $query->countQuery()->execute()->fetchField();
|
||||
|
||||
$this->assertEqual($count, 3, t('Counted the correct number of records.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that we can properly nest conditional clauses.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue