| 5 database.inc | db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) |
| 6 database.inc | db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) |
Rewrites node, taxonomy and comment queries. Use it for listing queries. Do not use FROM table1, table2 syntax, use JOIN instead.
Parameters
$query: Query to be rewritten.
$primary_table: Name or alias of the table which has the primary key field for this query. Typical table names would be: {blocks}, {comments}, {forum}, {node}, {menu}, {term_data} or {vocabulary}. However, it is more common to use the the usual table aliases: b, c, f, n, m, t or v.
$primary_field: Name of the primary field.
$args: An array of arguments, passed to the implementations of hook_db_rewrite_sql.
Return value
The original query with JOIN and WHERE statements inserted from hook_db_rewrite_sql implementations. nid is rewritten if needed.
Related topics
File
- includes/
database.inc, line 328 - Wrapper for database interface code.
Code
<?php
function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) {
list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args);
if ($distinct) {
$query = db_distinct_field($primary_table, $primary_field, $query);
}
if (!empty($where) || !empty($join)) {
$pattern = '{
# Beginning of the string
^
((?P<anonymous_view>
# Everything within this set of parentheses is named "anonymous view"
(?:
[^()]++ # anything not parentheses
|
\( (?P>anonymous_view) \) # an open parenthesis, more "anonymous view" and finally a close parenthesis.
)*
)[^()]+WHERE)
}x';
preg_match($pattern, $query, $matches);
if (!$where) {
$where = '1 = 1';
}
if ($matches) {
$n = strlen($matches[1]);
$second_part = substr($query, $n);
$first_part = substr($matches[1], 0, $n - 5) . " $join WHERE $where AND ( ";
// PHP 4 does not support strrpos for strings. We emulate it.
$haystack_reverse = strrev($second_part);
}
else {
$haystack_reverse = strrev($query);
}
// No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT
// reversed.
foreach (array('PUORG', 'REDRO', 'TIMIL') as $needle_reverse) {
$pos = strpos($haystack_reverse, $needle_reverse);
if ($pos !== FALSE) {
// All needles are five characters long.
$pos += 5;
break;
}
}
if ($matches) {
if ($pos === FALSE) {
$query = $first_part . $second_part . ')';
}
else {
$query = $first_part . substr($second_part, 0, -$pos) . ')' . substr($second_part, -$pos);
}
}
elseif ($pos === FALSE) {
$query .= " $join WHERE $where";
}
else {
$query = substr($query, 0, -$pos) . " $join WHERE $where " . substr($query, -$pos);
}
}
return $query;
}
?> Login or register to post comments
Comments
One subtle point to remember
One subtle point to remember is that when you're using db_rewrite_sql, the WHERE in the original query must be capitalized, or you'll get errors if it's adding anything to the query.
db_set_active may cause errors
using db_set_active before executing this function may cause errors. The node_access table is referenced by this function, and will not be available if you are temporarily using a different db.
Explanation
For new developers who have no idea what this function is about:
This function adds access control checks to SQL queries, so that the query returns only the rows the logged-in user is allowed to view. The actual checks necessary are determined by hook_db_rewrite_sql() and are thus extensible. For $primary_table='n', the core Node module implements hook_db_rewrite_sql() to tie into node access system ( hook_node_grants() etc).
Drupal 7 uses a query-tagging system
db_rewrite_sql() is not available in Drupal 7.
Instead, DB queries can be tagged (with 'node_access'), which allows hook_query_alter to recognise queries which should have node-access controls added.
For example:
<?php$nids = db_select('node', 'n')
->fields('n', array('nid', 'created'))
->condition('type', 'blog')
->condition('status', 1)
->orderBy('created', 'DESC')
->range(0, variable_get('feed_default_items', 10))
->addTag('node_access')
->execute()
->fetchCol();
The
->addTag('node_access')method marks the query for handling by the node access system.References: