function Query::prepare
Prepares the basic query with proper metadata/tags and base fields.
Return value
$this Returns the called object.
Throws
\Drupal\Core\Entity\Query\QueryException Thrown if the base table does not exist.
1 call to Query::prepare()
- QueryAggregate::prepare in core/
lib/ Drupal/ Core/ Entity/ Query/ Sql/ QueryAggregate.php - Prepares the basic query with proper metadata/tags and base fields.
2 methods override Query::prepare()
- Query::prepare in core/
modules/ workspaces/ src/ EntityQuery/ Query.php - Prepares the basic query with proper metadata/tags and base fields.
- QueryAggregate::prepare in core/
lib/ Drupal/ Core/ Entity/ Query/ Sql/ QueryAggregate.php - Prepares the basic query with proper metadata/tags and base fields.
File
-
core/
lib/ Drupal/ Core/ Entity/ Query/ Sql/ Query.php, line 97
Class
- Query
- The SQL storage entity query class.
Namespace
Drupal\Core\Entity\Query\SqlCode
protected function prepare() {
if ($this->allRevisions) {
if (!$base_table = $this->entityType
->getRevisionTable()) {
throw new QueryException("No revision table for " . $this->entityTypeId . ", invalid query.");
}
}
else {
if (!$base_table = $this->entityType
->getBaseTable()) {
throw new QueryException("No base table for " . $this->entityTypeId . ", invalid query.");
}
}
$simple_query = TRUE;
if ($this->entityType
->getDataTable()) {
$simple_query = FALSE;
}
$this->sqlQuery = $this->connection
->select($base_table, 'base_table', [
'conjunction' => $this->conjunction,
]);
// Reset the tables structure, as it might have been built for a previous
// execution of this query.
$this->tables = NULL;
$this->sqlQuery
->addMetaData('entity_type', $this->entityTypeId);
$id_field = $this->entityType
->getKey('id');
// Add the key field for fetchAllKeyed().
if (!$revision_field = $this->entityType
->getKey('revision')) {
// When there is no revision support, the key field is the entity key.
$this->sqlFields["base_table.{$id_field}"] = [
'base_table',
$id_field,
];
// Now add the value column for fetchAllKeyed(). This is always the
// entity id.
$this->sqlFields["base_table.{$id_field}" . '_1'] = [
'base_table',
$id_field,
];
}
else {
// When there is revision support, the key field is the revision key.
$this->sqlFields["base_table.{$revision_field}"] = [
'base_table',
$revision_field,
];
// Now add the value column for fetchAllKeyed(). This is always the
// entity id.
$this->sqlFields["base_table.{$id_field}"] = [
'base_table',
$id_field,
];
}
// Use a subquery with MAX() to only return the latest revision in the most
// optimal way. Note that this query is extremely performance-sensitive and
// changes here need to be tested on a database where there are many
// revisions and many entities.
if ($this->latestRevision && $revision_field) {
// Fetch all latest revision ids in a sub-query.
$revision_subquery = $this->connection
->select($base_table, 'subquery_base_table');
$revision_subquery->fields('subquery_base_table', [
$id_field,
]);
$revision_subquery->addExpression("MAX(subquery_base_table.{$revision_field})", 'maximum_revision_id');
$revision_subquery->groupBy("subquery_base_table.{$id_field}");
// Optimize the query if the query is only looking for a single entity.
// This improves the performance of
// \Drupal\Core\Entity\ContentEntityStorageBase::getLatestRevisionId().
$conditions = $this->condition
->conditions();
if (count($conditions) === 1 && isset($conditions[0]['field']) && $conditions[0]['field'] === $id_field) {
$revision_subquery->condition($id_field, $conditions[0]['value'], $conditions[0]['operator']);
}
// Restrict results only to latest ids.
$this->sqlQuery
->innerJoin($revision_subquery, 'sq_base_table', "base_table.{$id_field} = sq_base_table.{$id_field} AND base_table.{$revision_field} = sq_base_table.maximum_revision_id");
}
if (is_null($this->accessCheck)) {
throw new QueryException('Entity queries must explicitly set whether the query should be access checked or not. See Drupal\\Core\\Entity\\Query\\QueryInterface::accessCheck().');
}
if ($this->accessCheck) {
$this->sqlQuery
->addTag($this->entityTypeId . '_access');
}
$this->sqlQuery
->addTag('entity_query');
$this->sqlQuery
->addTag('entity_query_' . $this->entityTypeId);
// Add further tags added.
if (isset($this->alterTags)) {
foreach ($this->alterTags as $tag => $value) {
$this->sqlQuery
->addTag($tag);
}
}
// Add further metadata added.
if (isset($this->alterMetaData)) {
foreach ($this->alterMetaData as $key => $value) {
$this->sqlQuery
->addMetaData($key, $value);
}
}
// This now contains first the table containing entity properties and
// last the entity base table. They might be the same.
$this->sqlQuery
->addMetaData('all_revisions', $this->allRevisions);
$this->sqlQuery
->addMetaData('simple_query', $simple_query);
return $this;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.