diff -u b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php --- b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php +++ b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Query.php @@ -48,8 +48,10 @@ } $base_table = $entity_info['base table']; $entity_tables = array(); + $single_query = TRUE; if (isset($entity_info['data table'])) { $entity_tables[$entity_info['data table']] = drupal_get_schema($entity_info['data table']); + $single_query = FALSE; } // To make sure we query fields in the data table if there is one, add the // base after the data table. @@ -63,13 +65,17 @@ // information. $id_key = 'id'; if (!empty($entity_info['entity keys']['revision'])) { - $sqlQuery->addField('base_table', $entity_info['entity keys']['revision']); + $revision_field = $entity_info['entity keys']['revision']; + $fields[$revision_field] = TRUE; + $sqlQuery->addField('base_table', $revision_field); // Now revision id is column 0 and the value column is 1. $value_column = 1; if ($this->age == FIELD_LOAD_CURRENT) { $id_key = 'revision'; } } + $id_field = $entity_info['entity keys']['id']; + $fields[$id_field] = TRUE; $sqlQuery->addField('base_table', $entity_info['entity keys']['id']); if ($this->accessCheck) { $sqlQuery->addTag($this->entityType . '_access'); @@ -86,11 +92,30 @@ // This contains the relevant SQL field to be used when joining field // tables. $sqlQuery->addMetaData('field_id_field', $id_key == 'id' ? 'entity_id' : 'revision_id'); + $sqlQuery->addMetaData('single_query', $single_query); $this->condition->compile($sqlQuery); if ($this->sort) { $tables = new Tables($sqlQuery); foreach ($this->sort as $property => $direction) { - $sqlQuery->orderBy($tables->addField($property, 'LEFT'), $direction); + $sort[$property] = isset($fields[$property]) ? $property : $tables->addField($property, 'LEFT'); + } + $single_query = $sqlQuery->getMetaData('single_query'); + if (!$single_query) { + foreach (array_keys($fields) as $field) { + $sqlQuery->groupBy($field); + } + } + foreach ($sort as $property => $sql_alias) { + $direction = $this->sort[$property]; + if ($single_query || isset($fields[$property])) { + $sqlQuery->orderBy($sql_alias, $direction); + } + else { + $function = $direction == 'ASC' ? 'min' : 'max'; + $expression = "$function($sql_alias)"; + $sqlQuery->addExpression($expression, "order_by_{$property}_$direction"); + $sqlQuery->orderBy($expression); + } } } if ($this->range) { @@ -99,7 +124,6 @@ if ($this->count) { return $sqlQuery->countQuery()->execute()->fetchField(); } - if (!empty($GLOBALS['debug'])) debug(strtr($sqlQuery, $sqlQuery->getArguments())); return $sqlQuery->execute()->fetchAllKeyed(0, $value_column); } diff -u b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php --- b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php +++ b/core/modules/field/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Tables.php @@ -64,7 +64,6 @@ $sql_column = _field_sql_storage_columnname($field_name, $column); $table = $this->ensureFieldTable($field_name, $type); } - $this->sqlQuery->addField($table, $sql_column); return "$table.$sql_column"; } @@ -85,9 +84,6 @@ if (!isset($this->entityTables[$table])) { $id_field = $this->sqlQuery->getMetaData('entity_id_field'); $this->entityTables[$table] = $this->sqlQuery->addJoin($type, $table, NULL, "%alias.$id_field = base_table.$id_field"); - if ($type == 'LEFT') { - $this->sqlQuery->distinct(); - } } return $this->entityTables[$table]; } @@ -118,10 +114,10 @@ $table = $this->sqlQuery->getMetaData('age') == FIELD_LOAD_CURRENT ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field); $field_id_field = $this->sqlQuery->getMetaData('field_id_field'); $entity_id_field = $this->sqlQuery->getMetaData('entity_id_field'); - $this->fieldTables[$field_name] = $this->sqlQuery->addJoin($type, $table, NULL, "%alias.$field_id_field = base_table.$entity_id_field"); - if ($type == 'LEFT') { - $this->sqlQuery->distinct(); + if ($field['cardinality'] != 1) { + $this->sqlQuery->addMetaData('single_query', FALSE); } + $this->fieldTables[$field_name] = $this->sqlQuery->addJoin($type, $table, NULL, "%alias.$field_id_field = base_table.$entity_id_field"); } return $this->fieldTables[$field_name]; } diff -u b/core/modules/file/file.module b/core/modules/file/file.module --- b/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -1548,7 +1548,7 @@ // Fill the static cache, disregard $field and $field_type for now. if (!isset($references[$file->fid][$age])) { $references[$file->fid][$age] = array(); - $usage_list = file_usage_list($file); + $usage_list = file_usage()->listUsage($file); $file_usage_list = isset($usage_list['file']) ? $usage_list['file'] : array(); foreach ($file_usage_list as $entity_type => $entity_ids) { $entity_info = entity_get_info($entity_type); diff -u b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php --- b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php @@ -35,8 +35,8 @@ } function testEntityQuery() { - $figures = drupal_strtolower($this->randomName() . '_field_name'); - $greetings = drupal_strtolower($this->randomName() . '_field_name'); + $figures = drupal_strtolower($this->randomName()); + $greetings = drupal_strtolower($this->randomName()); foreach (array($figures => 'shape', $greetings => 'text') as $field_name => $field_type) { $field = array( 'field_name' => $field_name, @@ -159,16 +159,16 @@ ->sort('ftid', 'DESC') ->execute(); $this->assertResult(range(15, 1)); - $GLOBALS['debug'] = TRUE; - $this->queryResults = $factory->get('test_entity') + $query = $factory->get('test_entity') ->sort("$figures.color") ->sort("$greetings.langcode") - ->sort('ftid') - ->execute(); - // The result set for an SQL query is this, the groups indicate same color - // and same langcode. Within each group the last ftid sort decides. NULL - // comes first. Once an entity is fetched, it's place is settled, this is - // marked by a *: + ->sort('ftid'); + $count_query = clone $query; + $this->assertEqual(15, $count_query->count()->execute()); + $this->queryResults = $query->execute(); + // As we do not have any conditions, here are the possible colors and + // language codes, already in order, with the first occurence of the + // entity id marked with *: // 8 NULL pl * // 12 NULL pl * @@ -182,12 +182,12 @@ // 11 blue pl * // 14 blue pl * // 15 blue pl * - // + // 6 blue tr * // 7 blue tr * // 14 blue tr // 15 blue tr - // + // 1 red NULL // 3 red NULL @@ -195,13 +195,12 @@ // 11 red pl // 13 red pl * // 15 red pl - // + // 5 red tr * // 7 red tr // 13 red tr // 15 red tr $this->assertResult(8, 12, 4, 2, 3, 10, 11, 14, 15, 6, 7, 1, 9, 13, 5); - unset($GLOBALS['debug']); // Now update the 'merhaba' string to xsiemax which is not a meaningful // word but allows us to test revisions and string operations. @@ -232,6 +231,7 @@ $assert = $this->assertRevisionResult(range(16, 23), array(4, 5, 6, 7, 12, 13, 14, 15)); $results = $factory->get('test_entity') ->condition("$greetings.value", 'siema', 'CONTAINS') + ->sort('ftid') ->execute(); // This is the same as the previous one because xsiemax replaced merhaba // but also it contains the entities that siema originally but not @@ -253,6 +253,7 @@ $results = $factory->get('test_entity') ->condition("$greetings.value", 'a', 'ENDS_WITH') ->age(FIELD_LOAD_REVISION) + ->sort('ftid') ->execute(); // Now we get everything. $this->assertIdentical($results, $assert); only in patch2: unchanged: --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php @@ -105,7 +105,7 @@ public function view(EntityInterface $entity, $langcode, array $items) { '#theme' => 'field', '#weight' => $this->weight, '#title' => $instance['label'], - '#access' => field_access($field, 'view', $entity_type, $entity), + '#access' => field_access('view', $field, $entity_type, $entity), '#label_display' => $this->label, '#view_mode' => $this->viewMode, '#language' => $langcode,