summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/database/select.inc60
-rw-r--r--modules/field/field.multilingual.inc7
-rw-r--r--modules/field/tests/field.test10
-rw-r--r--modules/field/tests/field_test.module4
-rw-r--r--modules/simpletest/tests/database_test.test13
5 files changed, 78 insertions, 16 deletions
diff --git a/includes/database/select.inc b/includes/database/select.inc
index 535c29c85..d46abefdf 100644
--- a/includes/database/select.inc
+++ b/includes/database/select.inc
@@ -94,6 +94,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.
*
* Because this method returns by reference, alter hooks may edit the tables
@@ -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() {
diff --git a/modules/field/field.multilingual.inc b/modules/field/field.multilingual.inc
index e0b134849..600ed3010 100644
--- a/modules/field/field.multilingual.inc
+++ b/modules/field/field.multilingual.inc
@@ -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)) {
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index 7fbdba694..479b0a966 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -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'));
}
/**
diff --git a/modules/field/tests/field_test.module b/modules/field/tests/field_test.module
index 2eac091e2..f615129ff 100644
--- a/modules/field/tests/field_test.module
+++ b/modules/field/tests/field_test.module
@@ -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']);
+ }
}
/**
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index b2efa6672..e7f812893 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -1987,6 +1987,19 @@ class DatabaseSelectComplexTestCase extends DatabaseTestCase {
}
/**
+ * 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.
*/
function testNestedConditions() {