diff --git a/core/includes/database.inc b/core/includes/database.inc
index fc76b6f..7f1f278 100644
--- a/core/includes/database.inc
+++ b/core/includes/database.inc
@@ -34,20 +34,20 @@
* results that need to be presented on multiple pages, and the Tablesort
* Extender for generating appropriate queries for sortable tables.
*
- * For example, one might wish to return a list of the most recent 10 nodes
+ * For example, one might wish to return a list of the most recent 10 rows
* authored by a given user. Instead of directly issuing the SQL query
* @code
- * SELECT n.nid, n.title, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
+ * SELECT e.id, e.title, e.created FROM example e WHERE e.uid = $uid LIMIT 0, 10;
* @endcode
* one would instead call the Drupal functions:
* @code
- * $result = db_query_range('SELECT n.nid, n.title, n.created
- * FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
+ * $result = db_query_range('SELECT e.id, e.title, e.created
+ * FROM {example} e WHERE e.uid = :uid', 0, 10, array(':uid' => $uid));
* foreach ($result as $record) {
* // Perform operations on $record->title, etc. here.
* }
* @endcode
- * Curly braces are used around "node" to provide table prefixing via
+ * Curly braces are used around "example" to provide table prefixing via
* DatabaseConnection::prefixTables(). The explicit use of a user ID is pulled
* out into an argument passed to db_query() so that SQL injection attacks
* from user input can be caught and nullified. The LIMIT syntax varies between
@@ -69,7 +69,7 @@
*
* Named placeholders begin with a colon followed by a unique string. Example:
* @code
- * SELECT nid, title FROM {node} WHERE uid=:uid;
+ * SELECT id, title FROM {example} WHERE uid=:uid;
* @endcode
*
* ":uid" is a placeholder that will be replaced with a literal value when
@@ -81,7 +81,7 @@
*
* Unnamed placeholders are simply a question mark. Example:
* @code
- * SELECT nid, title FROM {node} WHERE uid=?;
+ * SELECT id, title FROM {example} WHERE uid=?;
* @endcode
*
* In this case, the array of arguments must be an indexed array of values to
@@ -91,11 +91,11 @@
* running a LIKE query the SQL wildcard character, %, should be part of the
* value, not the query itself. Thus, the following is incorrect:
* @code
- * SELECT nid, title FROM {node} WHERE title LIKE :title%;
+ * SELECT id, title FROM {example} WHERE title LIKE :title%;
* @endcode
* It should instead read:
* @code
- * SELECT nid, title FROM {node} WHERE title LIKE :title;
+ * SELECT id, title FROM {example} WHERE title LIKE :title;
* @endcode
* and the value for :title should include a % as appropriate. Again, note the
* lack of quotation marks around :title. Because the value is not inserted
@@ -109,7 +109,7 @@
* object-oriented API for defining a query structurally. For example, rather
* than:
* @code
- * INSERT INTO node (nid, title, body) VALUES (1, 'my title', 'my body');
+ * INSERT INTO {example} (id, uid, path, name) VALUES (1, 2, 'home', 'Home path');
* @endcode
* one would instead write:
* @code
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 48ee728..226a763 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -78,6 +78,9 @@ function entity_get_info($entity_type = NULL) {
// Drupal\Core\Entity\DatabaseStorageControllerInterface::buildQuery().
if (isset($entity_info[$name]['base table'])) {
$entity_info[$name]['schema_fields_sql']['base table'] = drupal_schema_fields_sql($entity_info[$name]['base table']);
+ if (isset($entity_info[$name]['data table'])) {
+ $entity_info[$name]['schema_fields_sql']['data table'] = drupal_schema_fields_sql($entity_info[$name]['data table']);
+ }
if (isset($entity_info[$name]['revision table'])) {
$entity_info[$name]['schema_fields_sql']['revision table'] = drupal_schema_fields_sql($entity_info[$name]['revision table']);
}
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 49ace44..4e58ff6 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -4687,26 +4687,25 @@ function _form_set_class(&$element, $class = array()) {
* $context['message'] = check_plain($node->label());
* }
*
- * // More advanced example: multi-step operation - load all nodes, five by five
+ * // More advanced example: multi-step operation - load all rows, five by five
* function my_function_2(&$context) {
* if (empty($context['sandbox'])) {
* $context['sandbox']['progress'] = 0;
- * $context['sandbox']['current_node'] = 0;
- * $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node}')->fetchField();
+ * $context['sandbox']['current_id'] = 0;
+ * $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT id) FROM {example}')->fetchField();
* }
* $limit = 5;
- * $result = db_select('node')
- * ->fields('node', array('nid'))
- * ->condition('nid', $context['sandbox']['current_node'], '>')
- * ->orderBy('nid')
+ * $result = db_select('example')
+ * ->fields('example', array('id'))
+ * ->condition('id', $context['sandbox']['current_id'], '>')
+ * ->orderBy('id')
* ->range(0, $limit)
* ->execute();
* foreach ($result as $row) {
- * $node = node_load($row->nid, TRUE);
- * $context['results'][] = $node->nid . ' : ' . check_plain($node->label());
+ * $context['results'][] = $row->id . ' : ' . check_plain($row->title);
* $context['sandbox']['progress']++;
- * $context['sandbox']['current_node'] = $node->nid;
- * $context['message'] = check_plain($node->label());
+ * $context['sandbox']['current_id'] = $row->id;
+ * $context['message'] = check_plain($row->title);
* }
* if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
* $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 5a5e544..4d53069 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -1463,10 +1463,10 @@ function menu_tree_collect_node_links(&$tree, &$node_links) {
function menu_tree_check_access(&$tree, $node_links = array()) {
if ($node_links) {
$nids = array_keys($node_links);
- $select = db_select('node', 'n');
- $select->addField('n', 'nid');
- $select->condition('n.status', 1);
- $select->condition('n.nid', $nids, 'IN');
+ $select = db_select('node_property_data', 'npd');
+ $select->addField('npd', 'nid');
+ $select->condition('npd.status', 1);
+ $select->condition('npd.nid', $nids, 'IN');
$select->addTag('node_access');
$nids = $select->execute()->fetchCol();
foreach ($nids as $nid) {
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
index c2a5a05..d5509a6 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
@@ -32,11 +32,11 @@ public function orderRandom() {
* yet selected.
*
* @code
- * $query = db_select('node', 'n');
- * $query->join('node_revision', 'nr', 'n.vid = nr.vid');
+ * $query = db_select('example', 'e');
+ * $query->join('example_revision', 'er', 'e.vid = er.vid');
* $query
* ->distinct()
- * ->fields('n')
+ * ->fields('e')
* ->orderBy('timestamp');
* @endcode
*
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
index 6342502..34f5ee8 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
@@ -89,6 +89,13 @@ class DatabaseStorageController implements EntityStorageControllerInterface {
protected $revisionKey;
/**
+ * The table that stores properties, if the entity has multilingual support.
+ *
+ * @var string
+ */
+ protected $dataTable;
+
+ /**
* The table that stores revisions, if the entity supports revisions.
*
* @var string
@@ -124,6 +131,11 @@ public function __construct($entityType) {
$this->uuidKey = FALSE;
}
+ // Check if the entity type has a dedicated table for properties.
+ if (!empty($this->entityInfo['data table'])) {
+ $this->dataTable = $this->entityInfo['data table'];
+ }
+
// Check if the entity type supports revisions.
if (!empty($this->entityInfo['entity keys']['revision'])) {
$this->revisionKey = $this->entityInfo['entity keys']['revision'];
@@ -324,6 +336,10 @@ protected function buildQuery($ids, $revision_id = FALSE) {
$query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
}
+ if (!empty($this->dataTable)) {
+ $query->join($this->dataTable, 'data', "data.{$this->idKey} = base.{$this->idKey}");
+ }
+
// Add fields from the {entity} table.
$entity_fields = $this->entityInfo['schema_fields_sql']['base table'];
@@ -348,6 +364,22 @@ protected function buildQuery($ids, $revision_id = FALSE) {
$query->addExpression('base.' . $this->revisionKey . ' = revision.' . $this->revisionKey, 'isDefaultRevision');
}
+ // Add fields from the entity data table.
+ if (!empty($this->dataTable)) {
+ // Add all fields from the {entity_data} table.
+ $entity_data_fields = drupal_map_assoc($this->entityInfo['schema_fields_sql']['data table']);
+ // The id field is provided by entity, so remove it.
+ unset($entity_data_fields[$this->idKey]);
+
+ if (!isset($entity_revision_fields)) {
+ $entity_revision_fields = array();
+ }
+
+ // Only add fields not covered by the base or the revision.
+ $entity_data_fields = array_diff($entity_data_fields, $entity_fields, $entity_revision_fields);
+ $query->fields('data', $entity_data_fields);
+ }
+
$query->fields('base', $entity_fields);
if ($ids) {
@@ -501,6 +533,14 @@ public function save(EntityInterface $entity) {
$this->preSave($entity);
$this->invokeHook('presave', $entity);
+ // Ensure the default langcode is stored in the base table.
+ // @todo clarify if it wouldn't be better to rename the column in the base
+ // table default_langcode as well.
+ if ($this->dataTable) {
+ $langcode = $entity->langcode;
+ $entity->langcode = $entity->default_langcode;
+ }
+
if (!$entity->isNew()) {
if ($entity->isDefaultRevision()) {
$return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey);
@@ -510,6 +550,11 @@ public function save(EntityInterface $entity) {
// with $isDefaultRevision = FALSE?
$return = FALSE;
}
+ // Ensure the appropriate langcodes are stored in the property data.
+ if ($this->dataTable) {
+ $entity->default_langcode = $entity->langcode;
+ $entity->langcode = $langcode;
+ }
if ($this->revisionKey) {
$this->saveRevision($entity);
}
@@ -519,6 +564,13 @@ public function save(EntityInterface $entity) {
}
else {
$return = drupal_write_record($this->entityInfo['base table'], $entity);
+ // Ensure the appropriate langcodes are stored in the property data.
+ // @todo clarify if it wouldn't be better to rename the column in the base
+ // table default_langcode as well.
+ if ($this->dataTable) {
+ $entity->default_langcode = $entity->langcode;
+ $entity->langcode = $langcode;
+ }
if ($this->revisionKey) {
$this->saveRevision($entity);
}
@@ -550,6 +602,18 @@ public function save(EntityInterface $entity) {
* The entity object.
*/
protected function saveRevision(EntityInterface $entity) {
+ // Ensure when saving properties in a new language a new revision is created.
+ // @todo try to find a nicer/unified way to do this.
+ if ($this->dataTable && !$entity->isNewRevision()) {
+ $query = db_select($this->revisionTable)
+ ->condition($this->idKey, $entity->id())
+ ->condition('langcode', $entity->langcode);
+ $query->addExpression('1');
+ if (!$query->execute()->fetchField()) {
+ $entity->setNewRevision();
+ }
+ }
+
// Convert the entity into an array as it might not have the same properties
// as the entity, it is just a raw structure.
$record = (array) $entity;
@@ -593,11 +657,32 @@ protected function preSave(EntityInterface $entity) { }
* Used after the entity is saved, but before invoking the insert or update
* hook.
*
- * @param $update
+ * @param boolean $update
* (bool) TRUE if the entity has been updated, or FALSE if it has been
* inserted.
*/
- protected function postSave(EntityInterface $entity, $update) { }
+ protected function postSave(EntityInterface $entity, $update) {
+ // Write the data into the property data table if one is available.
+ if ($this->dataTable) {
+ // @todo try to find a better way to deal with updates.
+ $query = db_select($this->entityInfo['data table'])
+ ->condition($this->idKey, $entity->id())
+ ->condition('langcode', $entity->langcode);
+ $query->addExpression('1');
+ if ($update && $query->execute()->fetchField()) {
+ // Update existing property data row.
+ $primary_keys = array(
+ $this->idKey,
+ 'langcode',
+ );
+ drupal_write_record($this->entityInfo['data table'], $entity, $primary_keys);
+ }
+ else {
+ // Insert new property data row.
+ drupal_write_record($this->entityInfo['data table'], $entity);
+ }
+ }
+ }
/**
* Acts on entities before they are deleted.
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
index f46c2c4..003d99c 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
@@ -96,7 +96,7 @@ function getFeedEditArray($feed_url = NULL) {
*/
function getDefaultFeedItemCount() {
// Our tests are based off of rss.xml, so let's find out how many elements should be related.
- $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField();
+ $feed_count = db_query_range('SELECT COUNT(DISTINCT nid) FROM {node_property_data} npd WHERE npd.promote = 1 AND npd.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField();
return $feed_count > 10 ? 10 : $feed_count;
}
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 7c43e28..69487c5 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -313,12 +313,12 @@ function book_block_view($delta = '') {
elseif ($current_bid) {
// Only display this block when the user is browsing a book.
$select = db_select('node', 'n')
- ->fields('n', array('title'))
+ ->fields('n', array('nid'))
->condition('n.nid', $node->book['bid'])
->addTag('node_access');
- $title = $select->execute()->fetchField();
+ $nid = $select->execute()->fetchField();
// Only show the block if the user has view access for the top-level node.
- if ($title) {
+ if ($nid) {
$tree = menu_tree_all_data($node->book['menu_name'], $node->book);
// There should only be one element at the top level.
$data = array_shift($tree);
@@ -394,20 +394,22 @@ function book_get_books() {
if ($nids) {
$query = db_select('book', 'b', array('fetch' => PDO::FETCH_ASSOC));
$query->join('node', 'n', 'b.nid = n.nid');
+ $query->join('node_property_data', 'npd', 'n.nid = npd.nid');
$query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
$query->addField('n', 'type', 'type');
- $query->addField('n', 'title', 'title');
$query->fields('b');
$query->fields('ml');
- $query->condition('n.nid', $nids, 'IN');
- $query->condition('n.status', 1);
+ $query->condition('npd.nid', $nids, 'IN');
+ $query->condition('npd.status', 1);
$query->orderBy('ml.weight');
$query->orderBy('ml.link_title');
$query->addTag('node_access');
$result2 = $query->execute();
foreach ($result2 as $link) {
+ $node = node_load($link['nid']);
$link['href'] = $link['link_path'];
$link['options'] = unserialize($link['options']);
+ $link['title'] = $node->label();
$all_books[$link['bid']] = $link;
}
}
diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc
index dcbd1bc..d66a79b 100644
--- a/core/modules/comment/comment.admin.inc
+++ b/core/modules/comment/comment.admin.inc
@@ -82,11 +82,10 @@ function comment_admin_overview($form, &$form_state, $arg) {
$query = db_select('comment', 'c')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
- $query->join('node', 'n', 'n.nid = c.nid');
- $query->addField('n', 'title', 'node_title');
+ $query->join('node_property_data', 'npd', 'npd.nid = c.nid');
$query->addTag('node_access');
$result = $query
- ->fields('c', array('cid', 'subject', 'name', 'changed'))
+ ->fields('c', array('cid', 'nid', 'subject', 'name', 'changed'))
->condition('c.status', $status)
->limit(50)
->orderByHeader($header)
@@ -97,8 +96,9 @@ function comment_admin_overview($form, &$form_state, $arg) {
// We collect a sorted list of node_titles during the query to attach to the
// comments later.
foreach ($result as $row) {
+ $node = node_load($row->nid);
$cids[] = $row->cid;
- $node_titles[] = $row->node_title;
+ $node_titles[] = $node->label();
}
$comments = comment_load_multiple($cids);
diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install
index f47151f..615e74c 100644
--- a/core/modules/comment/comment.install
+++ b/core/modules/comment/comment.install
@@ -34,14 +34,16 @@ function comment_uninstall() {
*/
function comment_enable() {
// Insert records into the node_comment_statistics for nodes that are missing.
- $query = db_select('node', 'n');
- $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid');
- $query->addField('n', 'created', 'last_comment_timestamp');
- $query->addField('n', 'uid', 'last_comment_uid');
- $query->addField('n', 'nid');
+ $query = db_select('node_property_data', 'npd');
+ $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = npd.nid');
+ $query->addField('npd', 'created', 'last_comment_timestamp');
+ $query->addField('npd', 'uid', 'last_comment_uid');
+ $query->addField('npd', 'nid');
$query->addExpression('0', 'comment_count');
$query->addExpression('NULL', 'last_comment_name');
$query->isNull('ncs.comment_count');
+ // @todo Replace by proper language handling.
+ $query->groupBy('npd.nid');
db_insert('node_comment_statistics')
->from($query)
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index df0a33a..ea32034 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -533,13 +533,13 @@ function comment_permalink($cid) {
*/
function comment_get_recent($number = 10) {
$query = db_select('comment', 'c');
- $query->innerJoin('node', 'n', 'n.nid = c.nid');
+ $query->innerJoin('node_property_data', 'npd', 'npd.nid = c.nid');
$query->addTag('node_access');
$query->addMetaData('base_table', 'comment');
$comments = $query
->fields('c')
->condition('c.status', COMMENT_PUBLISHED)
- ->condition('n.status', NODE_PUBLISHED)
+ ->condition('npd.status', NODE_PUBLISHED)
->orderBy('c.created', 'DESC')
// Additionally order by cid to ensure that comments with the same timestamp
// are returned in the exact order posted.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index 4d447a5..6b50964 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -223,7 +223,7 @@ protected function updateNodeStatistics($nid) {
}
else {
// Comments do not exist.
- $node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+ $node = db_query('SELECT uid, created FROM {node_property_data} WHERE nid = :nid LIMIT 1', array(':nid' => $nid))->fetchObject();
db_update('node_comment_statistics')
->fields(array(
'cid' => 0,
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index af2daa9..7c5beb9 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -806,14 +806,14 @@ function forum_forum_load($tid = NULL) {
$_forums = taxonomy_get_tree($vid, $tid, NULL, TRUE);
if (count($_forums)) {
- $query = db_select('node', 'n');
- $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
- $query->join('forum', 'f', 'n.vid = f.vid');
- $query->addExpression('COUNT(n.nid)', 'topic_count');
+ $query = db_select('node_property_data', 'npd');
+ $query->join('node_comment_statistics', 'ncs', 'npd.nid = ncs.nid');
+ $query->join('forum', 'f', 'npd.vid = f.vid');
+ $query->addExpression('COUNT(npd.nid)', 'topic_count');
$query->addExpression('SUM(ncs.comment_count)', 'comment_count');
$counts = $query
->fields('f', array('tid'))
- ->condition('n.status', 1)
+ ->condition('npd.status', 1)
->groupBy('tid')
->addTag('node_access')
->execute()
@@ -837,15 +837,15 @@ function forum_forum_load($tid = NULL) {
}
// Query "Last Post" information for this forum.
- $query = db_select('node', 'n');
- $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $forum->tid));
- $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
+ $query = db_select('node_property_data', 'npd');
+ $query->join('forum', 'f', 'npd.vid = f.vid AND f.tid = :tid', array(':tid' => $forum->tid));
+ $query->join('node_comment_statistics', 'ncs', 'npd.nid = ncs.nid');
$query->join('users', 'u', 'ncs.last_comment_uid = u.uid');
$query->addExpression('CASE ncs.last_comment_uid WHEN 0 THEN ncs.last_comment_name ELSE u.name END', 'last_comment_name');
$topic = $query
->fields('ncs', array('last_comment_timestamp', 'last_comment_uid'))
- ->condition('n.status', 1)
+ ->condition('npd.status', 1)
->orderBy('last_comment_timestamp', 'DESC')
->range(0, 1)
->addTag('node_access')
@@ -884,13 +884,13 @@ function forum_forum_load($tid = NULL) {
* The number of new posts in the forum that have not been read by the user.
*/
function _forum_topics_unread($term, $uid) {
- $query = db_select('node', 'n');
- $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $term));
- $query->leftJoin('history', 'h', 'n.nid = h.nid AND h.uid = :uid', array(':uid' => $uid));
- $query->addExpression('COUNT(n.nid)', 'count');
+ $query = db_select('node_property_data', 'npd');
+ $query->join('forum', 'f', 'npd.vid = f.vid AND f.tid = :tid', array(':tid' => $term));
+ $query->leftJoin('history', 'h', 'npd.nid = h.nid AND h.uid = :uid', array(':uid' => $uid));
+ $query->addExpression('COUNT(npd.nid)', 'count');
return $query
->condition('status', 1)
- ->condition('n.created', NODE_NEW_LIMIT, '>')
+ ->condition('npd.created', NODE_NEW_LIMIT, '>')
->isNull('h.nid')
->addTag('node_access')
->execute()
@@ -958,17 +958,17 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
if ($nids) {
$nodes = node_load_multiple($nids);
- $query = db_select('node', 'n')
+ $query = db_select('node_property_data', 'npd')
->extend('Drupal\Core\Database\Query\TableSortExtender');
- $query->fields('n', array('nid'));
+ $query->fields('npd', array('nid'));
- $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
+ $query->join('node_comment_statistics', 'ncs', 'npd.nid = ncs.nid');
$query->fields('ncs', array('cid', 'last_comment_uid', 'last_comment_timestamp', 'comment_count'));
$query->join('forum_index', 'f', 'f.nid = ncs.nid');
$query->addField('f', 'tid', 'forum_tid');
- $query->join('users', 'u', 'n.uid = u.uid');
+ $query->join('users', 'u', 'npd.uid = u.uid');
$query->addField('u', 'name');
$query->join('users', 'u2', 'ncs.last_comment_uid = u2.uid');
@@ -978,7 +978,8 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
$query
->orderBy('f.sticky', 'DESC')
->orderByHeader($forum_topic_list_header)
- ->condition('n.nid', $nids);
+ ->condition('npd.nid', $nids)
+ ->groupBy('npd.nid');
$result = array();
foreach ($query->execute() as $row) {
@@ -1386,7 +1387,7 @@ function _forum_update_forum_index($nid) {
}
else {
// Comments do not exist.
- $node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+ $node = db_query('SELECT uid, created FROM {node_property_data} WHERE nid = :nid LIMIT 1', array(':nid' => $nid))->fetchObject();
db_update('forum_index')
->fields( array(
'comment_count' => 0,
diff --git a/core/modules/language/language.api.php b/core/modules/language/language.api.php
index 6f19835..2ec0c4c 100644
--- a/core/modules/language/language.api.php
+++ b/core/modules/language/language.api.php
@@ -52,8 +52,8 @@ function hook_language_update($language) {
function hook_language_delete($language) {
// On nodes with this language, unset the language
db_update('node')
- ->fields(array('language' => ''))
- ->condition('language', $language->langcode)
+ ->fields(array('langcode' => ''))
+ ->condition('langcode', $language->langcode)
->execute();
}
diff --git a/core/modules/node/lib/Drupal/node/Node.php b/core/modules/node/lib/Drupal/node/Node.php
index 45d93f0..f519507 100644
--- a/core/modules/node/lib/Drupal/node/Node.php
+++ b/core/modules/node/lib/Drupal/node/Node.php
@@ -61,6 +61,13 @@ class Node extends Entity implements ContentEntityInterface {
public $langcode = LANGUAGE_NOT_SPECIFIED;
/**
+ * The node default language code.
+ *
+ * @var string
+ */
+ public $default_langcode;
+
+ /**
* The node title.
*
* @var string
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 5add3df..06ebea4 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -369,9 +369,9 @@ protected function submitNodeLanguage(array $form, array &$form_state) {
/**
* Form submission handler for the 'preview' action.
*
- * @param $form
+ * @param array $form
* An associative array containing the structure of the form.
- * @param $form_state
+ * @param array $form_state
* A reference to a keyed array containing the current state of the form.
*/
public function preview(array $form, array &$form_state) {
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
index 3993d24..1d999c3 100644
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php
@@ -66,9 +66,8 @@ protected function buildQuery($ids, $revision_id = FALSE) {
// alias timestamp to revision_timestamp and add revision_uid.
$query = parent::buildQuery($ids, $revision_id);
$fields =& $query->getFields();
- unset($fields['timestamp']);
$query->addField('revision', 'timestamp', 'revision_timestamp');
- $fields['uid']['table'] = 'base';
+ $fields['uid']['table'] = 'data';
$query->addField('revision', 'uid', 'revision_uid');
return $query;
}
@@ -80,7 +79,7 @@ protected function invokeHook($hook, EntityInterface $node) {
if ($hook == 'insert' || $hook == 'update') {
node_invoke($node, $hook);
}
- else if ($hook == 'predelete') {
+ elseif ($hook == 'predelete') {
// 'delete' is triggered in 'predelete' is here to preserve hook ordering
// from Drupal 7.
node_invoke($node, 'delete');
@@ -95,32 +94,19 @@ protected function invokeHook($hook, EntityInterface $node) {
protected function preSave(EntityInterface $node) {
// Before saving the node, set changed and revision times.
$node->changed = REQUEST_TIME;
+
+ // Make sure the default language is set.
+ if (empty($node->default_langcode)) {
+ $node->default_langcode = $node->langcode;
+ }
}
/**
* Overrides Drupal\Core\Entity\DatabaseStorageController::preSaveRevision().
*/
protected function preSaveRevision(array &$record, EntityInterface $entity) {
- if ($entity->isNewRevision()) {
- // When inserting either a new node or a new node revision, $node->log
- // must be set because {node_revision}.log is a text column and therefore
- // cannot have a default value. However, it might not be set at this
- // point (for example, if the user submitting a node form does not have
- // permission to create revisions), so we ensure that it is at least an
- // empty string in that case.
- // @todo: Make the {node_revision}.log column nullable so that we can
- // remove this check.
- if (!isset($record['log'])) {
- $record['log'] = '';
- }
- }
- elseif (!isset($record['log']) || $record['log'] === '') {
- // If we are updating an existing node without adding a new revision, we
- // need to make sure $node->log is unset whenever it is empty. As long as
- // $node->log is unset, drupal_write_record() will not attempt to update
- // the existing database column when re-saving the revision; therefore,
- // this code allows us to avoid clobbering an existing log entry with an
- // empty one.
+ // Make sure an existing log entry isn't overwritten unnecessarily.
+ if (empty($record['log'])) {
unset($record['log']);
}
@@ -133,7 +119,9 @@ protected function preSaveRevision(array &$record, EntityInterface $entity) {
/**
* Overrides Drupal\Core\Entity\DatabaseStorageController::postSave().
*/
- function postSave(EntityInterface $node, $update) {
+ protected function postSave(EntityInterface $node, $update) {
+ parent::postSave($node, $update);
+
// Update the node access table for this node, but only if it is the
// default revision. There's no need to delete existing records if the node
// is new.
@@ -144,7 +132,7 @@ function postSave(EntityInterface $node, $update) {
/**
* Overrides Drupal\Core\Entity\DatabaseStorageController::preDelete().
*/
- function preDelete($entities) {
+ protected function preDelete($entities) {
if (module_exists('search')) {
foreach ($entities as $id => $entity) {
search_reindex($entity->nid, 'node');
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
index a8e36b2..b6aaf1c 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
@@ -82,7 +82,7 @@ function testNodeAccessBasic() {
}
$this->drupalPost('node/add/article', $edit, t('Save'));
- $nid = db_query('SELECT nid FROM {node} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
+ $nid = db_query('SELECT nid FROM {node_property_data} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
$private_status = db_query('SELECT private FROM {node_access_test} where nid = :nid', array(':nid' => $nid))->fetchField();
$this->assertTrue($is_private == $private_status, 'The private status of the node was properly set in the node_access_test table.');
if ($is_private) {
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
index 3c02765..de68f7e 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
@@ -43,8 +43,9 @@ function testContentAdminSort() {
}
// Test that the default sort by node.changed DESC actually fires properly.
- $nodes_query = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes_query = db_select('node_property_data', 'npd')
+ ->distinct(TRUE)
+ ->fields('npd', array('nid'))
->orderBy('changed', 'DESC')
->execute()
->fetchCol();
@@ -58,8 +59,9 @@ function testContentAdminSort() {
// Compare the rendered HTML node list to a query for the nodes ordered by
// title to account for possible database-dependent sort order.
- $nodes_query = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes_query = db_select('node_property_data', 'npd')
+ ->distinct(TRUE)
+ ->fields('npd', array('nid'))
->orderBy('title')
->execute()
->fetchCol();
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
index edcb007..30c204b 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
@@ -72,13 +72,13 @@ function testRecentNodeBlock() {
$node3 = $this->drupalCreateNode($default_settings);
// Change the changed time for node so that we can test ordering.
- db_update('node')
+ db_update('node_property_data')
->fields(array(
'changed' => $node1->changed + 100,
))
->condition('nid', $node2->nid)
->execute();
- db_update('node')
+ db_update('node_property_data')
->fields(array(
'changed' => $node1->changed + 200,
))
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
index 9c3dd06..c512825 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
@@ -141,4 +141,5 @@ function testMultilingualDisplaySettings() {
));
$this->assertEqual(current($body), $node->body['en'][0]['value'], 'Node body found.');
}
+
}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php
new file mode 100644
index 0000000..22437f9
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Tests/NodePropertyMultilingualTestCase.php
@@ -0,0 +1,196 @@
+ 'Multilingual properties',
+ 'description' => 'Test multilingual support for properties.',
+ 'group' => 'Node',
+ );
+ }
+
+ public function setUp() {
+ parent::setUp();
+
+ // Create Basic page node type.
+ $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+
+ // Setup users.
+ $admin_user = $this->drupalCreateUser(array(
+ 'administer languages',
+ 'administer content types',
+ 'access administration pages',
+ 'create page content',
+ 'edit own page content',
+ ));
+ $this->drupalLogin($admin_user);
+
+ // Add a new languages.
+ $language = new Language(array(
+ 'langcode' => 'it',
+ 'name' => 'Italian',
+ ));
+ language_save($language);
+ $language = new Language(array(
+ 'langcode' => 'de',
+ 'name' => 'German',
+ ));
+ language_save($language);
+
+ // Enable URL language detection and selection.
+ $edit = array('language_interface[enabled][language-url]' => '1');
+ $this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
+
+ // Set "Basic page" content type to use multilingual support.
+ $edit = array(
+ 'language_configuration[language_hidden]' => FALSE,
+ );
+ $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
+ $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), 'Basic page content type has been updated.');
+
+ // Make node body translatable.
+ $field = field_info_field('body');
+ $field['translatable'] = TRUE;
+ field_update_field($field);
+ }
+
+ /**
+ * Test property translation.
+ */
+ public function testMultilingualProperties() {
+ $available_langcodes = array('en', 'it', 'de');
+ // Create different nodes with different default langcodes.
+ foreach ($available_langcodes as $default_langcode) {
+ // Create base node.
+ $title_values = array(
+ $default_langcode => $this->randomName(8),
+ );
+ $node = $this->drupalCreateNode(array(
+ 'title' => $title_values[$default_langcode],
+ 'body' => array($default_langcode => array(array($this->randomString(30)))),
+ 'langcode' => $default_langcode,
+ ));
+
+ $property_langcodes = array_diff($available_langcodes, array($default_langcode));
+
+ // Create properties in different languages.
+ $property_count = 1;
+ $expected_languages = array($default_langcode);
+ foreach ($property_langcodes as $langcode) {
+ $property_count++;
+ $expected_languages[] = $langcode;
+ $title_values[$langcode] = $this->randomName(8);
+
+ // Save properties in a different language.
+ $node->title = $title_values[$langcode];
+ $node->langcode = $langcode;
+ $node->save();
+
+ // Check consistency of property data.
+ $node_property_data = db_select('node_property_data')
+ ->fields('node_property_data')
+ ->condition('nid', $node->id())
+ ->execute()
+ ->fetchAll();
+ $this->assertEqual($property_count, count($node_property_data), 'Expected ' . $property_count . ' property rows found.');
+ $found_property_languages = array();
+ $found_property_default_languages = array();
+ foreach ($node_property_data as $node_property_data_raw) {
+ $found_property_languages[] = $node_property_data_raw->langcode;
+ $found_property_default_languages[$node_property_data_raw->default_langcode] = $node_property_data_raw->default_langcode;
+ $this->assertEqual($title_values[$node_property_data_raw->langcode], $node_property_data_raw->title, $node_property_data_raw->langcode . ': Language specific title found.');
+ }
+ $this->assertEqual($expected_languages, $found_property_languages, 'Expected property languages found.');
+ $this->assertEqual(array($default_langcode => $default_langcode), $found_property_default_languages, 'Default language of properties is consistent.');
+
+ // Check consistency of revisions.
+ $node_property_revision = db_select('node_property_revision')
+ ->fields('node_property_revision')
+ ->condition('nid', $node->id())
+ ->orderBy('vid')
+ ->execute()
+ ->fetchAll();
+ $this->assertEqual($property_count, count($node_property_revision), 'Expected ' . $property_count . ' property revision rows found.');
+ $found_revision_languages = array();
+ $found_revision_default_languages = array();
+ foreach ($node_property_revision as $node_property_revision_raw) {
+ $found_revision_languages[] = $node_property_revision_raw->langcode;
+ $found_revision_default_languages[$node_property_revision_raw->default_langcode] = $node_property_revision_raw->default_langcode;
+ $this->assertEqual($title_values[$node_property_revision_raw->langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': Language specific title found.');
+ }
+ $this->assertEqual($expected_languages, $found_revision_languages, 'Expected property revision languages found.');
+ $this->assertEqual(array($default_langcode => $default_langcode), $found_revision_default_languages, 'Default language of revisions is consistent.');
+ }
+
+ // Check revisioning.
+ $title_revision_values = array();
+ foreach ($available_langcodes as $langcode) {
+ $title_revision_values[$langcode] = $this->randomName(8);
+ // Create new revision in the same language.
+ $old_revision_id = $node->getRevisionId();
+ $node->title = $title_revision_values[$langcode];
+ $node->langcode = $langcode;
+ $node->setNewRevision();
+ $node->save();
+
+ // Check consistency of property data.
+ $node_property_data = db_select('node_property_data')
+ ->fields('node_property_data')
+ ->condition('nid', $node->id())
+ ->condition('langcode', $node->langcode)
+ ->execute()
+ ->fetchAll();
+ if ($this->assertEqual(1, count($node_property_data), 'Two property rows found.')) {
+ $this->assertNotEqual($old_revision_id, $node_property_data[0]->vid, $node_property_data_raw->langcode . ': New Revision id set.');
+ $this->assertEqual($title_revision_values[$langcode], $node_property_data[0]->title, $node_property_data_raw->langcode . ': Revisioned title found.');
+ }
+
+ $node_property_revision = db_select('node_property_revision')
+ ->fields('node_property_revision')
+ ->condition('nid', $node->id())
+ ->condition('langcode', $node->langcode)
+ ->orderBy('vid')
+ ->execute()
+ ->fetchAll();
+ $this->assertEqual(2, count($node_property_revision), 'Two property revision rows found.');
+ foreach ($node_property_revision as $node_property_revision_raw) {
+ if ($node_property_revision_raw->vid == $node->getRevisionId()) {
+ $this->assertEqual($title_revision_values[$langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': title of new revision found.');
+ }
+ else {
+ $this->assertEqual($title_values[$langcode], $node_property_revision_raw->title, $node_property_revision_raw->langcode . ': title of old revision found.');
+ }
+ }
+ }
+
+ // Check if the default language is untouched.
+ $node_raw_data = db_select('node')
+ ->fields('node')
+ ->condition('nid', $node->id())
+ ->execute()
+ ->fetchAll();
+ $this->assertEqual($default_langcode, $node_raw_data[0]->langcode, 'Default language unchanged.');
+ }
+ }
+}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
index 6bb752f..1543f0f 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
@@ -97,12 +97,12 @@ function testRevisions() {
$this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
array('%revision-date' => format_date($nodes[1]->revision_timestamp),
'@type' => 'Basic page', '%title' => $nodes[1]->label())), 'Revision deleted.');
- $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, 'Revision not found.');
+ $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_property_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, 'Revision not found.');
// Set the revision timestamp to an older date to make sure that the
// confirmation message correctly displays the stored revision date.
$old_revision_date = REQUEST_TIME - 86400;
- db_update('node_revision')
+ db_update('node_property_revision')
->condition('vid', $nodes[2]->vid)
->fields(array(
'timestamp' => $old_revision_date,
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index 2ca2d3e..ba9f4c4 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -136,12 +136,16 @@ function node_build_filter_query(SelectInterface $query) {
foreach ($filter_data as $index => $filter) {
list($key, $value) = $filter;
switch ($key) {
+ case 'type':
+ $query->condition('n.' . $key, $value);
+ break;
+
+ // Part of node property data table.
case 'status':
// Note: no exploitable hole as $key/$value have already been checked when submitted
list($key, $value) = explode('-', $value, 2);
- case 'type':
case 'language':
- $query->condition('n.' . $key, $value);
+ $query->condition('npd.' . $key, $value);
break;
}
}
@@ -464,7 +468,7 @@ function node_admin_nodes() {
$header = array(
'title' => array(
'data' => t('Title'),
- 'field' => 'n.title',
+ 'field' => 'npd.title',
),
'type' => array(
'data' => t('Content type'),
@@ -477,42 +481,43 @@ function node_admin_nodes() {
),
'status' => array(
'data' => t('Status'),
- 'field' => 'n.status',
+ 'field' => 'npd.status',
),
'changed' => array(
'data' => t('Updated'),
- 'field' => 'n.changed',
+ 'field' => 'npd.changed',
'sort' => 'desc',
'class' => array(RESPONSIVE_PRIORITY_LOW)
,)
);
if ($multilingual) {
- $header['language_name'] = array('data' => t('Language'), 'field' => 'n.langcode', 'class' => array(RESPONSIVE_PRIORITY_LOW));
+ $header['language_name'] = array('data' => t('Language'), 'field' => 'npd.langcode', 'class' => array(RESPONSIVE_PRIORITY_LOW));
}
$header['operations'] = array('data' => t('Operations'));
$query = db_select('node', 'n')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
+ $query->innerJoin('node_property_data', 'npd', 'npd.nid = n.nid');
node_build_filter_query($query);
if (!user_access('bypass node access')) {
// If the user is able to view their own unpublished nodes, allow them
// to see these in addition to published nodes. Check that they actually
// have some unpublished nodes to view before adding the condition.
- if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) {
+ if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT DISTINCT nid FROM {node_property_data} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) {
$query->condition(db_or()
- ->condition('n.status', 1)
- ->condition('n.nid', $own_unpublished, 'IN')
+ ->condition('npd.status', 1)
+ ->condition('npd.nid', $own_unpublished, 'IN')
);
}
else {
// If not, restrict the query to published nodes.
- $query->condition('n.status', 1);
+ $query->condition('npd.status', 1);
}
}
$nids = $query
- ->fields('n',array('nid'))
+ ->fields('npd', array('nid'))
->limit(50)
->orderByHeader($header)
->addTag('node_access')
@@ -677,14 +682,14 @@ function node_admin_nodes_submit($form, &$form_state) {
*/
function node_multiple_delete_confirm($form, &$form_state, $nodes) {
$form['nodes'] = array('#prefix' => '
', '#tree' => TRUE);
+ $node_entities = node_load_multiple(array_keys($nodes));
// array_filter returns only elements with TRUE values
foreach ($nodes as $nid => $value) {
- $title = db_query('SELECT title FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchField();
$form['nodes'][$nid] = array(
'#type' => 'hidden',
'#value' => $nid,
'#prefix' => '',
- '#suffix' => check_plain($title) . "\n",
+ '#suffix' => check_plain($node_entities[$nid]->label()) . "\n",
);
}
$form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index a9c2c36..c2df993 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -27,7 +27,7 @@ function node_schema() {
// Defaults to NULL in order to avoid a brief period of potential
// deadlocks on the index.
'vid' => array(
- 'description' => 'The current {node_revision}.vid version identifier.',
+ 'description' => 'The current {node_property_revision}.vid version identifier.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE,
@@ -47,6 +47,68 @@ function node_schema() {
'not null' => TRUE,
'default' => '',
),
+ 'tnid' => array(
+ 'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ 'translate' => array(
+ 'description' => 'A boolean indicating whether this translation page needs to be updated.',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ ),
+ 'indexes' => array(
+ 'node_type' => array(array('type', 4)),
+ 'tnid' => array('tnid'),
+ 'translate' => array('translate'),
+ ),
+ 'unique keys' => array(
+ 'vid' => array('vid'),
+ 'uuid' => array('uuid'),
+ ),
+ 'foreign keys' => array(
+ 'node_revision' => array(
+ 'table' => 'node_revision',
+ 'columns' => array('vid' => 'vid'),
+ ),
+ ),
+ 'primary key' => array('nid'),
+ );
+
+ // Node property storage.
+ $schema['node_property_data'] = array(
+ 'description' => 'Base table for node properties.',
+ 'fields' => array(
+ 'nid' => array(
+ 'description' => 'The primary identifier for a node.',
+ 'type' => 'serial',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ ),
+ 'vid' => array(
+ 'description' => 'The current {node_property_revision}.vid version identifier.',
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ ),
+ 'langcode' => array(
+ 'description' => 'The {language}.langcode of this node.',
+ 'type' => 'varchar',
+ 'length' => 12,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'default_langcode' => array(
+ 'description' => 'The default {language}.langcode of this node.',
+ 'type' => 'varchar',
+ 'length' => 12,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
'title' => array(
'description' => 'The title of this node, always treated as non-markup plain text.',
'type' => 'varchar',
@@ -97,187 +159,187 @@ function node_schema() {
'not null' => TRUE,
'default' => 0,
),
- 'tnid' => array(
- 'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
- 'type' => 'int',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'translate' => array(
- 'description' => 'A boolean indicating whether this translation page needs to be updated.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
),
'indexes' => array(
- 'node_changed' => array('changed'),
- 'node_created' => array('created'),
- 'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
- 'node_status_type' => array('status', 'type', 'nid'),
- 'node_title_type' => array('title', array('type', 4)),
- 'node_type' => array(array('type', 4)),
- 'uid' => array('uid'),
- 'tnid' => array('tnid'),
- 'translate' => array('translate'),
+ 'node_created' => array('created'),
+ 'node_changed' => array('changed'),
+ 'node_frontpage' => array('promote', 'status', 'sticky', 'changed'),
+ 'node_status' => array('status', 'nid'),
+ 'node_title' => array('title'),
+ 'uid' => array('uid'),
),
'unique keys' => array(
'vid' => array('vid'),
- 'uuid' => array('uuid'),
),
'foreign keys' => array(
- 'node_revision' => array(
- 'table' => 'node_revision',
- 'columns' => array('vid' => 'vid'),
+ 'node_base' => array(
+ 'table' => 'node',
+ 'columns' => array('nid' => 'nid'),
),
'node_author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
),
- 'primary key' => array('nid'),
+ 'primary key' => array('nid', 'vid', 'langcode'),
);
- $schema['node_access'] = array(
- 'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
+ // Node property revision storage.
+ $schema['node_property_revision'] = array(
+ 'description' => 'Stores information about each saved version of a {node}.',
'fields' => array(
'nid' => array(
- 'description' => 'The {node}.nid this record affects.',
+ 'description' => 'The {node} this version belongs to.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
- 'default' => 0,
),
- 'gid' => array(
- 'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
- 'type' => 'int',
+ 'vid' => array(
+ 'description' => 'The primary identifier for this version.',
+ 'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
- 'default' => 0,
),
- 'realm' => array(
- 'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
+ 'langcode' => array(
+ 'description' => 'The {language}.langcode of this version.',
+ 'type' => 'varchar',
+ 'length' => 12,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'default_langcode' => array(
+ 'description' => 'The default {language}.langcode of this version.',
+ 'type' => 'varchar',
+ 'length' => 12,
+ 'not null' => TRUE,
+ 'default' => '',
+ ),
+ 'title' => array(
+ 'description' => 'The title of this version, always treated as non-markup plain text.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
- 'grant_view' => array(
- 'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
+ 'uid' => array(
+ 'description' => 'The {users}.uid that created this version.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
- 'size' => 'tiny',
),
- 'grant_update' => array(
- 'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
+ 'status' => array(
+ 'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 1,
+ ),
+ 'comment' => array(
+ 'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
'type' => 'int',
- 'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
- 'size' => 'tiny',
),
- 'grant_delete' => array(
- 'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
+ 'promote' => array(
+ 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ 'sticky' => array(
+ 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ ),
+ 'log' => array(
+ 'description' => 'The log entry explaining the changes in this version.',
+ 'type' => 'text',
+ 'not null' => FALSE,
+ 'size' => 'big',
+ ),
+ 'timestamp' => array(
+ 'description' => 'The Unix timestamp when this revision was saved.',
'type' => 'int',
- 'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
- 'size' => 'tiny',
),
),
- 'primary key' => array('nid', 'gid', 'realm'),
+ 'indexes' => array(
+ 'nid' => array('nid'),
+ 'uid' => array('uid'),
+ ),
+ 'unique keys' => array(
+ 'vid' => array('vid'),
+ ),
'foreign keys' => array(
- 'affected_node' => array(
+ 'versioned_node' => array(
'table' => 'node',
'columns' => array('nid' => 'nid'),
),
- ),
+ 'version_author' => array(
+ 'table' => 'users',
+ 'columns' => array('uid' => 'uid'),
+ ),
+ ),
+ 'primary key' => array('nid', 'vid', 'langcode'),
);
- $schema['node_revision'] = array(
- 'description' => 'Stores information about each saved version of a {node}.',
+ $schema['node_access'] = array(
+ 'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
'fields' => array(
'nid' => array(
- 'description' => 'The {node} this version belongs to.',
+ 'description' => 'The {node}.nid this record affects.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
- 'vid' => array(
- 'description' => 'The primary identifier for this version.',
- 'type' => 'serial',
- 'unsigned' => TRUE,
- 'not null' => TRUE,
- ),
- 'uid' => array(
- 'description' => 'The {users}.uid that created this version.',
+ 'gid' => array(
+ 'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
- 'title' => array(
- 'description' => 'The title of this version.',
+ 'realm' => array(
+ 'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
- 'log' => array(
- 'description' => 'The log entry explaining the changes in this version.',
- 'type' => 'text',
- 'not null' => TRUE,
- 'size' => 'big',
- ),
- 'timestamp' => array(
- 'description' => 'A Unix timestamp indicating when this version was created.',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0,
- ),
- 'status' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 1,
- ),
- 'comment' => array(
- 'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
+ 'grant_view' => array(
+ 'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
'type' => 'int',
+ 'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
+ 'size' => 'tiny',
),
- 'promote' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
+ 'grant_update' => array(
+ 'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
'type' => 'int',
+ 'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
+ 'size' => 'tiny',
),
- 'sticky' => array(
- 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
+ 'grant_delete' => array(
+ 'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
'type' => 'int',
+ 'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
+ 'size' => 'tiny',
),
),
- 'indexes' => array(
- 'nid' => array('nid'),
- 'uid' => array('uid'),
- ),
- 'primary key' => array('vid'),
+ 'primary key' => array('nid', 'gid', 'realm'),
'foreign keys' => array(
- 'versioned_node' => array(
+ 'affected_node' => array(
'table' => 'node',
'columns' => array('nid' => 'nid'),
),
- 'version_author' => array(
- 'table' => 'users',
- 'columns' => array('uid' => 'uid'),
- ),
),
);
@@ -365,7 +427,7 @@ function node_schema() {
'type' => 'int',
'not null' => TRUE,
'default' => 0,
- 'size' => 'tiny'
+ 'size' => 'tiny',
),
'orig_type' => array(
'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
@@ -692,6 +754,160 @@ function node_update_8007() {
}
/**
+ * Add dedicated tables for node properties.
+ */
+function node_update_8008() {
+ $schema = node_schema();
+ // Create property table if necessary.
+ if (!db_table_exists('node_property_data')) {
+ db_create_table('node_property_data', $schema['node_property_data']);
+ }
+
+ // Create property revision table if necessary.
+ if (!db_table_exists('node_property_revision')) {
+ db_create_table('node_property_revision', $schema['node_property_revision']);
+ }
+}
+
+/**
+ * Move property data to dedicated table.
+ */
+function node_update_8009(&$sandbox) {
+ if (!isset($sandbox['progress'])) {
+ $sandbox['progress'] = 0;
+ $sandbox['last'] = (int) db_query('SELECT npd.nid FROM {node_property_data npd} ORDER BY nid DESC')->fetchField();
+ $sandbox['max'] = db_query('SELECT COUNT(*) FROM {node} n LEFT JOIN {node_property_data} npd ON npd.nid = n.nid WHERE npd.nid IS NULL')->fetchField();
+ }
+
+ // Create initial property data set if necessary.
+ if (!empty($sandbox['max'])) {
+ $source_query = db_select('node')
+ ->fields('node', array(
+ 'nid',
+ 'vid',
+ 'langcode',
+ 'title',
+ 'uid',
+ 'status',
+ 'created',
+ 'changed',
+ 'comment',
+ 'promote',
+ 'sticky',
+ ))
+ ->range(0, 10)
+ ->condition('nid', $sandbox['last'], '>')
+ ->orderBy('nid');
+ $source_query->addField('node', 'langcode', 'default_langcode');
+ db_insert('node_property_data')->from($source_query)->execute();
+ $sandbox['last'] = db_query('SELECT npd.nid FROM {node_property_data} npd ORDER BY nid DESC')->fetchField();
+ $sandbox['progress'] += 10;
+ }
+
+ $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
+}
+
+/**
+ * Move property revisions to dedicated table.
+ */
+function node_update_8010(&$sandbox) {
+ if (!isset($sandbox['progress'])) {
+ $sandbox['progress'] = 0;
+ $sandbox['last'] = (int) db_query('SELECT npr.vid FROM {node_property_revision} npr ORDER BY vid DESC')->fetchField();
+ $sandbox['max'] = db_query('SELECT COUNT(*) FROM {node_revision} nr LEFT JOIN {node_property_revision} npr ON npr.vid = nr.vid WHERE npr.vid IS NULL')->fetchField();
+ }
+
+ // Create initial revision set if necessary.
+ if (!empty($sandbox['max'])) {
+ $source_query = db_select('node_revision', 'nr')
+ ->fields('nr', array(
+ 'nid',
+ 'vid',
+ 'uid',
+ 'title',
+ 'status',
+ 'comment',
+ 'promote',
+ 'sticky',
+ 'log',
+ 'timestamp',
+ ))
+ ->range(0, 10)
+ ->condition('nr.vid', $sandbox['last'], '>')
+ ->orderBy('nr.vid');
+ $source_query->innerJoin('node_property_data', 'npd', 'npd.nid = nr.nid');
+ $source_query->addField('npd', 'langcode');
+ $source_query->addField('npd', 'default_langcode');
+
+ db_insert('node_property_revision')->from($source_query)->execute();
+ $sandbox['last'] = db_query('SELECT npr.vid FROM {node_property_revision} npr ORDER BY vid DESC')->fetchField();
+ $sandbox['progress'] += 10;
+ }
+
+ $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
+}
+
+/**
+ * Cleanup old tables after finishing switch to dedicated property tables.
+ */
+function node_update_8011() {
+ $old_base_table_fields = array(
+ 'title',
+ 'uid',
+ 'status',
+ 'created',
+ 'changed',
+ 'comment',
+ 'promote',
+ 'sticky',
+ );
+ $old_base_table_indexes = array(
+ 'node_created',
+ 'node_changed',
+ 'node_frontpage',
+ 'node_status_type',
+ 'node_title_type',
+ 'node_type',
+ 'uid',
+ );
+
+ $node_count = db_select('node')->countQuery()->execute()->fetchColumn();
+ $node_revision_count = db_select('node_revision')->countQuery()->execute()->fetchColumn();
+ $node_property_count = db_select('node_property_data')->countQuery()->execute()->fetchColumn();
+ $node_property_revision_count = db_select('node_property_revision')->countQuery()->execute()->fetchColumn();
+
+ // Modify original tables if possible and necessary.
+ if ($node_property_count == $node_count) {
+ // Drop deprecated indexes.
+ foreach ($old_base_table_indexes as $old_index) {
+ if (db_index_exists('node', $old_index)) {
+ db_drop_index('node', $old_index);
+ }
+ }
+ // Recreate index.
+ if (!db_index_exists('node', 'node_type')) {
+ db_add_index('node', 'node_type', array(array('type', 4)));
+ }
+ // Drop deprecated fields.
+ foreach ($old_base_table_fields as $deprecated_base_field) {
+ if (db_field_exists('node', $deprecated_base_field)) {
+ db_drop_field('node', $deprecated_base_field);
+ }
+ }
+ }
+ else {
+ throw new DrupalUpdateException('The data migration from the node to the new node_property_data table seems to be inconsistent.');
+ }
+
+ if (db_table_exists('node_revision') && $node_revision_count == $node_property_revision_count) {
+ db_drop_table('node_revision');
+ }
+ else {
+ throw new DrupalUpdateException('The data migration from the node_revision to the new node_property_revision table seems to be inconsistent.');
+ }
+}
+
+/**
* @} End of "addtogroup updates-7.x-to-8.x"
* The next series of updates should start at 9000.
*/
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 55989de..d76a752 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -203,7 +203,8 @@ function node_entity_info() {
'default' => 'Drupal\node\NodeFormController',
),
'base table' => 'node',
- 'revision table' => 'node_revision',
+ 'data table' => 'node_property_data',
+ 'revision table' => 'node_property_revision',
'uri callback' => 'node_uri',
'fieldable' => TRUE,
'entity keys' => array(
@@ -1407,16 +1408,17 @@ function node_search_execute($keys = NULL, $conditions = NULL) {
->extend('Drupal\search\SearchQuery')
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
$query->join('node', 'n', 'n.nid = i.sid');
+ $query->join('node_property_data', 'npd', 'npd.nid = n.nid');
$query
- ->condition('n.status', 1)
+ ->condition('npd.status', 1)
->addTag('node_access')
->searchExpression($keys, 'node');
// Insert special keywords.
$query->setOption('type', 'n.type');
- $query->setOption('langcode', 'n.langcode');
+ $query->setOption('langcode', 'npd.langcode');
if ($query->setOption('term', 'ti.tid')) {
- $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
+ $query->join('taxonomy_index', 'ti', 'npd.nid = ti.nid');
}
// Only continue if the first pass query matches.
if (!$query->executeFirstPass()) {
@@ -1478,12 +1480,12 @@ function node_ranking() {
'sticky' => array(
'title' => t('Content is sticky at top of lists'),
// The sticky flag is either 0 or 1, which is automatically normalized.
- 'score' => 'n.sticky',
+ 'score' => 'npd.sticky',
),
'promote' => array(
'title' => t('Content is promoted to the front page'),
// The promote flag is either 0 or 1, which is automatically normalized.
- 'score' => 'n.promote',
+ 'score' => 'npd.promote',
),
);
@@ -1492,7 +1494,7 @@ function node_ranking() {
$ranking['recent'] = array(
'title' => t('Recently posted'),
// Exponential decay with half-life of 6 months, starting at last indexed node
- 'score' => 'POW(2.0, (GREATEST(n.created, n.changed) - :node_cron_last) * 6.43e-8)',
+ 'score' => 'POW(2.0, (GREATEST(npd.created, npd.changed) - :node_cron_last) * 6.43e-8)',
'arguments' => array(':node_cron_last' => $node_cron_last),
);
}
@@ -1507,8 +1509,9 @@ function node_user_cancel($edit, $account, $method) {
case 'user_cancel_block_unpublish':
// Unpublish nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
- $nodes = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes = db_select('node_property_data', 'npd')
+ ->distinct(TRUE)
+ ->fields('npd', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
@@ -1518,14 +1521,15 @@ function node_user_cancel($edit, $account, $method) {
case 'user_cancel_reassign':
// Anonymize nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
- $nodes = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes = db_select('node_property_data', 'npd')
+ ->distinct(TRUE)
+ ->fields('npd', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_mass_update($nodes, array('uid' => 0));
// Anonymize old revisions.
- db_update('node_revision')
+ db_update('node_property_revision')
->fields(array('uid' => 0))
->condition('uid', $account->uid)
->execute();
@@ -1543,14 +1547,15 @@ function node_user_cancel($edit, $account, $method) {
function node_user_predelete($account) {
// Delete nodes (current revisions).
// @todo Introduce node_mass_delete() or make node_mass_update() more flexible.
- $nodes = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes = db_select('node_property_data', 'npd')
+ ->distinct(TRUE)
+ ->fields('npd', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_delete_multiple($nodes);
// Delete old revisions.
- $revisions = db_query('SELECT vid FROM {node_revision} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol();
+ $revisions = db_query('SELECT vid FROM {node_property_revision} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol();
foreach ($revisions as $revision) {
node_revision_delete($revision);
}
@@ -1649,7 +1654,7 @@ function _node_revision_access(Node $node, $op = 'view', $account = NULL, $langc
// different revisions so there is no need for a separate database check.
// Also, if you try to revert to or delete the default revision, that's
// not good.
- if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
+ if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_property_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
$access[$cid] = FALSE;
}
elseif (user_access('administer nodes', $account)) {
@@ -1920,7 +1925,7 @@ function node_page_title(Node $node) {
* A unix timestamp indicating the last time the node was changed.
*/
function node_last_changed($nid) {
- return db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed;
+ return db_query('SELECT changed FROM {node_property_data} WHERE nid = :nid ORDER BY changed DESC LIMIT 1', array(':nid' => $nid))->fetch()->changed;
}
/**
@@ -1934,7 +1939,15 @@ function node_last_changed($nid) {
*/
function node_revision_list(Node $node) {
$revisions = array();
- $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = :nid ORDER BY r.vid DESC', array(':nid' => $node->nid));
+ $result = db_query('SELECT npr.vid, npr.title, npr.log, npr.uid, n.vid AS current_vid, npr.timestamp, u.name ' .
+ 'FROM {node_property_revision} npr ' .
+ 'LEFT JOIN {node} n ON n.vid = npr.vid ' .
+ 'LEFT JOIN {node_property_data} npd ON npd.nid = n.nid ' .
+ 'INNER JOIN {users} u ON u.uid = npr.uid ' .
+ 'WHERE npr.nid = :nid ' .
+ 'ORDER BY npr.vid DESC',
+ array(':nid' => $node->nid)
+ );
foreach ($result as $revision) {
$revisions[$revision->vid] = $revision;
}
@@ -2025,26 +2038,26 @@ function node_block_save($delta = '', $edit = array()) {
* nodes visible to the current user.
*/
function node_get_recent($number = 10) {
- $query = db_select('node', 'n');
+ $query = db_select('node_property_data', 'npd');
if (!user_access('bypass node access')) {
// If the user is able to view their own unpublished nodes, allow them
// to see these in addition to published nodes. Check that they actually
// have some unpublished nodes to view before adding the condition.
- if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
+ if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT DISTINCT nid FROM {node_property_data} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
$query->condition(db_or()
- ->condition('n.status', NODE_PUBLISHED)
- ->condition('n.nid', $own_unpublished, 'IN')
+ ->condition('npd.status', NODE_PUBLISHED)
+ ->condition('npd.nid', $own_unpublished, 'IN')
);
}
else {
// If not, restrict the query to published nodes.
- $query->condition('n.status', NODE_PUBLISHED);
+ $query->condition('npd.status', NODE_PUBLISHED);
}
}
$nids = $query
- ->fields('n', array('nid'))
- ->orderBy('n.changed', 'DESC')
+ ->fields('npd', array('nid'))
+ ->orderBy('npd.changed', 'DESC')
->range(0, $number)
->addTag('node_access')
->execute()
@@ -2296,11 +2309,12 @@ function node_feed($nids = FALSE, $channel = array()) {
$rss_config = config('system.rss');
if ($nids === FALSE) {
- $nids = db_select('node', 'n')
- ->fields('n', array('nid', 'created'))
- ->condition('n.promote', 1)
- ->condition('n.status', 1)
- ->orderBy('n.created', 'DESC')
+ $nids = db_select('node_property_data', 'npd')
+ ->fields('npd', array('nid', 'created'))
+ ->condition('npd.promote', 1)
+ ->condition('npd.status', 1)
+ ->groupBy('npd.nid')
+ ->orderBy('npd.created', 'DESC')
->range(0, $rss_config->get('items.limit'))
->addTag('node_access')
->execute()
@@ -2407,12 +2421,13 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) {
*/
function node_page_default() {
$site_config = config('system.site');
- $select = db_select('node', 'n')
- ->fields('n', array('nid', 'sticky', 'created'))
- ->condition('n.promote', 1)
- ->condition('n.status', 1)
- ->orderBy('n.sticky', 'DESC')
- ->orderBy('n.created', 'DESC')
+ $select = db_select('node_property_data', 'npd')
+ ->fields('npd', array('nid', 'sticky', 'created'))
+ ->condition('npd.promote', 1)
+ ->condition('npd.status', 1)
+ ->groupBy('npd.nid')
+ ->orderBy('npd.sticky', 'DESC')
+ ->orderBy('npd.created', 'DESC')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->limit(variable_get('default_nodes_main', 10))
->addTag('node_access');
@@ -3140,7 +3155,7 @@ function _node_query_node_access_alter($query, $type) {
if (!($table_info instanceof SelectInterface)) {
$table = $table_info['table'];
// If the node table is in the query, it wins immediately.
- if ($table == 'node') {
+ if ($table == 'node' || $table == 'node_property_data') {
$base_table = $table;
break;
}
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index a3afa7f..4efec1a 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -380,7 +380,7 @@ function node_revision_delete_confirm_submit($form, &$form_state) {
watchdog('content', '@type: deleted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->label(), '%revision' => $node_revision->vid));
drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($node_revision->revision_timestamp), '@type' => node_get_type_label($node_revision), '%title' => $node_revision->label())));
$form_state['redirect'] = 'node/' . $node_revision->nid;
- if (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node_revision->nid))->fetchField() > 1) {
+ if (db_query('SELECT COUNT(vid) FROM {node_property_revision} WHERE nid = :nid', array(':nid' => $node_revision->nid))->fetchField() > 1) {
$form_state['redirect'] .= '/revisions';
}
}
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
index 2cfe9e5..385d993 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
@@ -58,8 +58,8 @@ function testAutoExpire() {
// Test expiration. Since REQUEST_TIME is a constant and we don't
// want to keep SimpleTest waiting until the moment of expiration arrives,
// we forcibly change the expiration date in the database.
- $created = db_query('SELECT created FROM {node} WHERE nid = :nid', array(':nid' => $poll_nid))->fetchField();
- db_update('node')
+ $created = db_query('SELECT created FROM {node_property_data} WHERE nid = :nid', array(':nid' => $poll_nid))->fetchField();
+ db_update('node_property_data')
->fields(array('created' => $created - ($poll_expiration * 1.01)))
->condition('nid', $poll_nid)
->execute();
diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module
index c85f121..0ac65ee 100644
--- a/core/modules/poll/poll.module
+++ b/core/modules/poll/poll.module
@@ -137,12 +137,13 @@ function poll_block_info() {
function poll_block_view($delta = '') {
if (user_access('access content')) {
// Retrieve the latest poll.
- $select = db_select('node', 'n');
- $select->join('poll', 'p', 'p.nid = n.nid');
- $select->fields('n', array('nid'))
- ->condition('n.status', 1)
+ $select = db_select('node_property_data', 'npd');
+ $select->join('poll', 'p', 'p.nid = npd.nid');
+ $select->fields('npd', array('nid'))
+ ->distinct(TRUE)
+ ->condition('npd.status', 1)
->condition('p.active', 1)
- ->orderBy('n.created', 'DESC')
+ ->orderBy('npd.created', 'DESC')
->range(0, 1)
->addTag('node_access');
@@ -165,7 +166,7 @@ function poll_block_view($delta = '') {
* Closes polls that have exceeded their allowed runtime.
*/
function poll_cron() {
- $nids = db_query('SELECT p.nid FROM {poll} p INNER JOIN {node} n ON p.nid = n.nid WHERE (n.created + p.runtime) < :request_time AND p.active = :active AND p.runtime <> :runtime', array(':request_time' => REQUEST_TIME, ':active' => 1, ':runtime' => 0))->fetchCol();
+ $nids = db_query('SELECT p.nid FROM {poll} p INNER JOIN {node_property_data} npd ON p.nid = npd.nid WHERE (npd.created + p.runtime) < :request_time AND p.active = :active AND p.runtime <> :runtime', array(':request_time' => REQUEST_TIME, ':active' => 1, ':runtime' => 0))->fetchCol();
if (!empty($nids)) {
db_update('poll')
->fields(array('active' => 0))
diff --git a/core/modules/poll/poll.pages.inc b/core/modules/poll/poll.pages.inc
index b67d8f9..da1138c 100644
--- a/core/modules/poll/poll.pages.inc
+++ b/core/modules/poll/poll.pages.inc
@@ -16,24 +16,24 @@
function poll_page() {
$polls_per_page = 15;
- $count_select = db_select('node', 'n');
+ $count_select = db_select('node_property_data', 'npd');
$count_select->addExpression('COUNT(*)', 'expression');
- $count_select->join('poll', 'p', 'p.nid = n.nid');
- $count_select->condition('n.status', 1);
+ $count_select->join('poll', 'p', 'p.nid = npd.nid');
+ $count_select->condition('npd.status', 1);
+ $count_select->groupBy('npd.nid');
// List all polls.
- $select = db_select('node', 'n');
- $select->join('poll', 'p', 'p.nid = n.nid');
- $select->join('poll_choice', 'c', 'c.nid = n.nid');
+ $select = db_select('node_property_data', 'npd');
+ $select->join('poll', 'p', 'p.nid = npd.nid');
+ $select->join('poll_choice', 'c', 'c.nid = npd.nid');
$select->addExpression('SUM(c.chvotes)', 'votes');
- $select = $select->fields('n', array('nid', 'title', 'created'))
+ $select = $select->fields('npd', array('nid', 'title', 'created'))
->fields('p', array('active'))
- ->condition('n.status', 1)
- ->orderBy('n.created', 'DESC')
- ->groupBy('n.nid')
- ->groupBy('n.title')
+ ->condition('npd.status', 1)
+ ->orderBy('npd.created', 'DESC')
+ ->groupBy('npd.nid')
->groupBy('p.active')
- ->groupBy('n.created')
+ ->groupBy('npd.created')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->limit($polls_per_page)
->addTag('node_access');
@@ -41,10 +41,11 @@ function poll_page() {
$queried_nodes = $select->execute()
->fetchAllAssoc('nid');
+ $node_entities = node_load_multiple(array_keys($queried_nodes));
+
$output = '';
- // Do not use $node->label() here because $node comes from the database.
foreach ($queried_nodes as $node) {
- $output .= '- ' . l($node->title, "node/$node->nid") . ' - ' . format_plural($node->votes, '1 vote', '@count votes') . ' - ' . ($node->active ? t('open') : t('closed')) . '
';
+ $output .= '- ' . l($node_entities[$node->nid]->label(), "node/$node->nid") . ' - ' . format_plural($node->votes, '1 vote', '@count votes') . ' - ' . ($node->active ? t('open') : t('closed')) . '
';
}
$output .= '
';
$output .= theme('pager');
diff --git a/core/modules/search/search.api.php b/core/modules/search/search.api.php
index 0dd0a84..a643b03 100644
--- a/core/modules/search/search.api.php
+++ b/core/modules/search/search.api.php
@@ -117,8 +117,8 @@ function hook_search_reset() {
* @ingroup search
*/
function hook_search_status() {
- $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
- $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
+ $total = db_query('SELECT COUNT(*) FROM {example} WHERE status = 1')->fetchField();
+ $remaining = db_query("SELECT COUNT(*) FROM {example} e LEFT JOIN {search_dataset} d ON d.type = 'example' AND d.sid = e.id WHERE e.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
return array('remaining' => $remaining, 'total' => $total);
}
@@ -198,17 +198,17 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
$query = db_select('search_index', 'i', array('target' => 'slave'))
->extend('Drupal\search\SearchQuery')
->extend('Drupal\Core\Database\Query\PagerSelectExtender');
- $query->join('node', 'n', 'n.nid = i.sid');
+ $query->join('example', 'e', 'e.id = i.sid');
$query
- ->condition('n.status', 1)
- ->addTag('node_access')
- ->searchExpression($keys, 'node');
+ ->condition('e.status', 1)
+ ->addTag('example_access')
+ ->searchExpression($keys, 'example');
// Insert special keywords.
- $query->setOption('type', 'n.type');
- $query->setOption('langcode', 'n.langcode');
+ $query->setOption('type', 'e.type');
+ $query->setOption('langcode', 'e.langcode');
if ($query->setOption('term', 'ti.tid')) {
- $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
+ $query->join('taxonomy_index', 'ti', 'e.id = ti.id');
}
// Only continue if the first pass query matches.
if (!$query->executeFirstPass()) {
@@ -225,29 +225,29 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
$results = array();
foreach ($find as $item) {
// Render the node.
- $node = node_load($item->sid);
- $build = node_view($node, 'search_result', $item->langcode);
+ $example = example_load($item->sid);
+ $build = example_view($example, 'search_result', $item->langcode);
unset($build['#theme']);
- $node->rendered = drupal_render($build);
+ $example->rendered = drupal_render($build);
// Fetch comments for snippet.
- $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node, $item->langcode);
+ $example->rendered .= ' ' . module_invoke('comment', 'node_update_index', $example, $item->langcode);
- $extra = module_invoke_all('node_search_result', $node, $item->langcode);
+ $extra = module_invoke_all('node_search_result', $example, $item->langcode);
$language = language_load($item->langcode);
- $uri = $node->uri();
+ $uri = $example->uri();
$results[] = array(
'link' => url($uri['path'], array_merge($uri['options'], array('absolute' => TRUE, 'language' => $language))),
- 'type' => check_plain(node_get_type_label($node)),
- 'title' => $node->label($item->langcode),
- 'user' => theme('username', array('account' => $node)),
- 'date' => $node->get('changed', $item->langcode),
- 'node' => $node,
+ 'type' => check_plain(node_get_type_label($example)),
+ 'title' => $example->label($item->langcode),
+ 'user' => theme('username', array('account' => $example)),
+ 'date' => $example->get('changed', $item->langcode),
+ 'node' => $example,
'extra' => $extra,
'score' => $item->calculated_score,
- 'snippet' => search_excerpt($keys, $node->rendered, $item->langcode),
- 'langcode' => $node->langcode,
+ 'snippet' => search_excerpt($keys, $example->rendered, $item->langcode),
+ 'langcode' => $example->langcode,
);
}
return $results;
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 315ae7a..5747283 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -647,10 +647,9 @@ function search_index($sid, $module, $text, $langcode) {
if (preg_match('!(?:node|book)/(?:view/)?([0-9]+)!i', $path, $match)) {
$linknid = $match[1];
if ($linknid > 0) {
- $node = db_query('SELECT title, nid, vid FROM {node} WHERE nid = :nid', array(':nid' => $linknid), array('target' => 'slave'))->fetchObject();
$link = TRUE;
- // Do not use $node->label(), $node comes from the database.
- $linktitle = $node->title;
+ $node = node_load($linknid);
+ $linktitle = $node->label();
}
}
}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index c5dbd0b..c38415d 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -240,7 +240,7 @@ protected function drupalCreateNode($settings = array()) {
$node->save();
// Small hack to link revisions to our test user.
- db_update('node_revision')
+ db_update('node_property_revision')
->fields(array('uid' => $node->uid))
->condition('vid', $node->vid)
->execute();
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index 8469e52..f653fb3 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -263,17 +263,18 @@ function statistics_cron() {
*/
function statistics_title_list($dbfield, $dbrows) {
if (in_array($dbfield, array('totalcount', 'daycount', 'timestamp'))) {
- $query = db_select('node', 'n');
+ $query = db_select('node_property_data', 'npd');
$query->addTag('node_access');
- $query->join('node_counter', 's', 'n.nid = s.nid');
- $query->join('users', 'u', 'n.uid = u.uid');
+ $query->join('node_counter', 's', 'npd.nid = s.nid');
+ $query->join('users', 'u', 'npd.uid = u.uid');
return $query
- ->fields('n', array('nid', 'title'))
+ ->fields('npd', array('nid', 'title'))
->fields('u', array('uid', 'name'))
->condition($dbfield, 0, '<>')
- ->condition('n.status', 1)
+ ->condition('npd.status', 1)
->orderBy($dbfield, 'DESC')
+ ->groupBy('npd.nid')
->range(0, $dbrows)
->execute();
}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/RegressionTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/RegressionTest.php
index 4e4f364..df0e530 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/RegressionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/RegressionTest.php
@@ -64,7 +64,7 @@ function testDBFieldExists() {
* Tests the db_index_exists() function.
*/
function testDBIndexExists() {
- $this->assertIdentical(TRUE, db_index_exists('node', 'node_created'), 'Returns true for existent index.');
+ $this->assertIdentical(TRUE, db_index_exists('node', 'node_type'), 'Returns true for existent index.');
$this->assertIdentical(FALSE, db_index_exists('node', 'nosuchindex'), 'Returns false for nonexistent index.');
}
}
diff --git a/core/modules/tracker/tracker.module b/core/modules/tracker/tracker.module
index 7060a87..8ecbb1e 100644
--- a/core/modules/tracker/tracker.module
+++ b/core/modules/tracker/tracker.module
@@ -83,7 +83,7 @@ function tracker_cron() {
$batch_size = config('tracker.settings')->get('cron_index_limit');
if ($max_nid > 0) {
$last_nid = FALSE;
- $result = db_query_range('SELECT nid, uid, status FROM {node} WHERE nid <= :max_nid ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'slave'));
+ $result = db_query_range('SELECT nid, uid, status FROM {node_property_data} WHERE nid <= :max_nid GROUP BY nid ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'slave'));
$count = 0;
@@ -268,7 +268,7 @@ function tracker_comment_delete($comment) {
* The node updated timestamp or comment timestamp.
*/
function _tracker_add($nid, $uid, $changed) {
- $node = db_query('SELECT nid, status, uid, changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+ $node = db_query('SELECT nid, status, uid, changed FROM {node_property_data} WHERE nid = :nid ORDER BY changed DESC, status DESC LIMIT 1', array(':nid' => $nid))->fetchObject();
// Adding a comment can only increase the changed timestamp, so our
// calculation here is simple.
@@ -307,7 +307,7 @@ function _tracker_add($nid, $uid, $changed) {
* is the greatest.
*/
function _tracker_calculate_changed($nid) {
- $changed = db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid), array('target' => 'slave'))->fetchField();
+ $changed = db_query('SELECT changed FROM {node_property_data} WHERE nid = :nid ORDER BY changed DESC LIMIT 1', array(':nid' => $nid), array('target' => 'slave'))->fetchField();
$latest_comment = db_query_range('SELECT cid, changed FROM {comment} WHERE nid = :nid AND status = :status ORDER BY changed DESC', 0, 1, array(
':nid' => $nid,
':status' => COMMENT_PUBLISHED,
@@ -329,7 +329,7 @@ function _tracker_calculate_changed($nid) {
* The last changed timestamp of the node.
*/
function _tracker_remove($nid, $uid = NULL, $changed = NULL) {
- $node = db_query('SELECT nid, status, uid, changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+ $node = db_query('SELECT nid, status, uid, changed FROM {node_property_data} WHERE nid = :nid ORDER BY changed DESC, status DESC LIMIT 1', array(':nid' => $nid))->fetchObject();
// The user only keeps his or her subscription if both of the following are true:
// (1) The node exists.
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index 853f50d..131eba7 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -50,9 +50,20 @@ function tracker_page($account = NULL, $set_title = FALSE) {
$rows = array();
if (!empty($nodes)) {
// Now, get the data and put into the placeholder array.
- $result = db_query('SELECT n.nid, n.title, n.type, n.changed, n.uid, u.name, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid WHERE n.nid IN (:nids)', array(':nids' => array_keys($nodes)), array('target' => 'slave'));
+ $result = db_query('SELECT npd.nid, npd.title, n.type, npd.changed, npd.uid, u.name, l.comment_count ' .
+ 'FROM {node_property_data} npd ' .
+ 'INNER JOIN {node} n ON n.nid = npd.nid ' .
+ 'INNER JOIN {node_comment_statistics} l ON npd.nid = l.nid ' .
+ 'INNER JOIN {users} u ON npd.uid = u.uid ' .
+ 'WHERE npd.nid IN (:nids) ' .
+ 'GROUP BY npd.nid ' .
+ 'ORDER BY npd.changed DESC ',
+ array(':nids' => array_keys($nodes)), array('target' => 'slave')
+ );
+ $node_entities = node_load_multiple(array_keys($nodes));
foreach ($result as $node) {
$node->last_activity = $nodes[$node->nid]->changed;
+ $node->title = $node_entities[$node->nid]->label();
$nodes[$node->nid] = $node;
}
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index e7f22fd..e47cb4f 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -486,11 +486,13 @@ function translation_node_get_translations($tnid) {
if (!isset($translations[$tnid])) {
$translations[$tnid] = array();
- $result = db_select('node', 'n')
- ->fields('n', array('nid', 'type', 'uid', 'status', 'title', 'langcode'))
+ $query = db_select('node_property_data', 'npd');
+ $query->innerJoin('node', 'n', 'n.nid = npd.nid AND n.langcode = npd.langcode');
+ $query->fields('npd', array('nid', 'uid', 'status', 'title', 'langcode'))
+ ->fields('n', array('type'))
->condition('n.tnid', $tnid)
- ->addTag('node_access')
- ->execute();
+ ->addTag('node_access');
+ $result = $query->execute();
foreach ($result as $node) {
$translations[$tnid][$node->langcode] = $node;
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index 0c3002c..ec4bdea 100644
--- a/core/modules/user/user.api.php
+++ b/core/modules/user/user.api.php
@@ -104,8 +104,8 @@ function hook_user_cancel($edit, $account, $method) {
case 'user_cancel_block_unpublish':
// Unpublish nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
- $nodes = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes = db_select('node_property_data', 'npd')
+ ->fields('npd', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
@@ -115,14 +115,14 @@ function hook_user_cancel($edit, $account, $method) {
case 'user_cancel_reassign':
// Anonymize nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
- $nodes = db_select('node', 'n')
- ->fields('n', array('nid'))
+ $nodes = db_select('node_property_data', 'npd')
+ ->fields('npd', array('nid'))
->condition('uid', $account->uid)
->execute()
->fetchCol();
node_mass_update($nodes, array('uid' => 0));
// Anonymize old revisions.
- db_update('node_revision')
+ db_update('node_property_revision')
->fields(array('uid' => 0))
->condition('uid', $account->uid)
->execute();