database.inc

  1. drupal
    1. 4.6 includes/database.inc
    2. 4.7 includes/database.inc
    3. 5 includes/database.inc
    4. 6 includes/database.inc
    5. 7 includes/database/database.inc
    6. 7 includes/database/sqlite/database.inc
    7. 7 includes/database/mysql/database.inc
    8. 7 includes/database/pgsql/database.inc
    9. 8 core/includes/database.inc

Wrapper for database interface code.

Functions & methods

NameDescription
db_escape_tableRestrict a dynamic tablename to safe characters.
db_prefix_tablesAppend a database prefix to all tables in a query.
db_queryRuns a basic query in the active database.
db_querydDebugging version of db_query().
db_rewrite_sqlRewrites node, taxonomy and comment queries. Use it for listing queries. Do not use FROM table1, table2 syntax, use JOIN instead.
db_set_activeActivate a database for future queries.
_db_query_callbackHelper function for db_query().
_db_rewrite_sqlHelper function for db_rewrite_sql.

Constants

NameDescription
DB_QUERY_REGEXP

File

includes/database.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Wrapper for database interface code.
  5. */
  6. /**
  7. * @defgroup database Database abstraction layer
  8. * @{
  9. * Allow the use of different database servers using the same code base.
  10. *
  11. * Drupal provides a slim database abstraction layer to provide developers with
  12. * the ability to support multiple database servers easily. The intent of this
  13. * layer is to preserve the syntax and power of SQL as much as possible, while
  14. * letting Drupal control the pieces of queries that need to be written
  15. * differently for different servers and provide basic security checks.
  16. *
  17. * Most Drupal database queries are performed by a call to db_query() or
  18. * db_query_range(). Module authors should also consider using pager_query() for
  19. * queries that return results that need to be presented on multiple pages, and
  20. * tablesort_sql() for generating appropriate queries for sortable tables.
  21. *
  22. * For example, one might wish to return a list of the most recent 10 nodes
  23. * authored by a given user. Instead of directly issuing the SQL query
  24. * @code
  25. * SELECT n.title, n.body, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
  26. * @endcode
  27. * one would instead call the Drupal functions:
  28. * @code
  29. * $result = db_query_range('SELECT n.title, n.body, n.created
  30. * FROM {node} n WHERE n.uid = %d', $uid, 0, 10);
  31. * while ($node = db_fetch_object($result)) {
  32. * // Perform operations on $node->body, etc. here.
  33. * }
  34. * @endcode
  35. * Curly braces are used around "node" to provide table prefixing via
  36. * db_prefix_tables(). The explicit use of a user ID is pulled out into an
  37. * argument passed to db_query() so that SQL injection attacks from user input
  38. * can be caught and nullified. The LIMIT syntax varies between database servers,
  39. * so that is abstracted into db_query_range() arguments. Finally, note the
  40. * common pattern of iterating over the result set using db_fetch_object().
  41. */
  42. /**
  43. * Append a database prefix to all tables in a query.
  44. *
  45. * Queries sent to Drupal should wrap all table names in curly brackets. This
  46. * function searches for this syntax and adds Drupal's table prefix to all
  47. * tables, allowing Drupal to coexist with other systems in the same database if
  48. * necessary.
  49. *
  50. * @param $sql
  51. * A string containing a partial or entire SQL query.
  52. * @return
  53. * The properly-prefixed string.
  54. */
  55. function db_prefix_tables($sql) {
  56. global $db_prefix;
  57. if (is_array($db_prefix)) {
  58. if (array_key_exists('default', $db_prefix)) {
  59. $tmp = $db_prefix;
  60. unset($tmp['default']);
  61. foreach ($tmp as $key => $val) {
  62. $sql = strtr($sql, array('{'. $key. '}' => $val. $key));
  63. }
  64. return strtr($sql, array('{' => $db_prefix['default'], '}' => ''));
  65. }
  66. else {
  67. foreach ($db_prefix as $key => $val) {
  68. $sql = strtr($sql, array('{'. $key. '}' => $val. $key));
  69. }
  70. return strtr($sql, array('{' => '', '}' => ''));
  71. }
  72. }
  73. else {
  74. return strtr($sql, array('{' => $db_prefix, '}' => ''));
  75. }
  76. }
  77. /**
  78. * Activate a database for future queries.
  79. *
  80. * If it is necessary to use external databases in a project, this function can
  81. * be used to change where database queries are sent. If the database has not
  82. * yet been used, it is initialized using the URL specified for that name in
  83. * Drupal's configuration file. If this name is not defined, a duplicate of the
  84. * default connection is made instead.
  85. *
  86. * Be sure to change the connection back to the default when done with custom
  87. * code.
  88. *
  89. * @param $name
  90. * The name assigned to the newly active database connection. If omitted, the
  91. * default connection will be made active.
  92. *
  93. * @return the name of the previously active database or FALSE if non was found.
  94. */
  95. function db_set_active($name = 'default') {
  96. global $db_url, $db_type, $active_db;
  97. static $db_conns, $active_name = FALSE;
  98. if (!isset($db_conns[$name])) {
  99. // Initiate a new connection, using the named DB URL specified.
  100. if (is_array($db_url)) {
  101. $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default'];
  102. }
  103. else {
  104. $connect_url = $db_url;
  105. }
  106. $db_type = substr($connect_url, 0, strpos($connect_url, '://'));
  107. $handler = "./includes/database.$db_type.inc";
  108. if (is_file($handler)) {
  109. include_once $handler;
  110. }
  111. else {
  112. drupal_maintenance_theme();
  113. drupal_set_title('Unsupported database type');
  114. print theme('maintenance_page', '<p>The database type '. theme('placeholder', $db_type) .' is unsupported. Please use either <var>mysql</var> for MySQL 3.x &amp; 4.0.x databases, <var>mysqli</var> for MySQL 4.1.x+ databases, or <var>pgsql</var> for PostgreSQL databases. The database information is in your <code>settings.php</code> file.</p>
  115. <p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
  116. exit;
  117. }
  118. $db_conns[$name] = db_connect($connect_url);
  119. }
  120. $previous_name = $active_name;
  121. // Set the active connection.
  122. $active_name = $name;
  123. $active_db = $db_conns[$name];
  124. return $previous_name;
  125. }
  126. /**
  127. * Helper function for db_query().
  128. */
  129. function _db_query_callback($match, $init = FALSE) {
  130. static $args = NULL;
  131. if ($init) {
  132. $args = $match;
  133. return;
  134. }
  135. switch ($match[1]) {
  136. case '%d': // We must use type casting to int to convert false/null/(true?)
  137. return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe
  138. case '%s':
  139. return db_escape_string(array_shift($args));
  140. case '%%':
  141. return '%';
  142. case '%f':
  143. return (float) array_shift($args);
  144. case '%b': // binary data
  145. return db_encode_blob(array_shift($args));
  146. }
  147. }
  148. define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/');
  149. /**
  150. * Runs a basic query in the active database.
  151. *
  152. * User-supplied arguments to the query should be passed in as separate
  153. * parameters so that they can be properly escaped to avoid SQL injection
  154. * attacks.
  155. *
  156. * @param $query
  157. * A string containing an SQL query.
  158. * @param ...
  159. * A variable number of arguments which are substituted into the query
  160. * using printf() syntax. Instead of a variable number of query arguments,
  161. * you may also pass a single array containing the query arguments.
  162. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  163. * in '') and %%.
  164. *
  165. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  166. * and TRUE values to decimal 1.
  167. *
  168. * @return
  169. * A database query result resource, or FALSE if the query was not
  170. * executed correctly.
  171. */
  172. function db_query($query) {
  173. $args = func_get_args();
  174. array_shift($args);
  175. $query = db_prefix_tables($query);
  176. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  177. $args = $args[0];
  178. }
  179. _db_query_callback($args, TRUE);
  180. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  181. return _db_query($query);
  182. }
  183. /**
  184. * Debugging version of db_query().
  185. *
  186. * Echoes the query to the browser.
  187. */
  188. function db_queryd($query) {
  189. $args = func_get_args();
  190. array_shift($args);
  191. $query = db_prefix_tables($query);
  192. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  193. $args = $args[0];
  194. }
  195. _db_query_callback($args, TRUE);
  196. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  197. return _db_query($query, 1);
  198. }
  199. /**
  200. * Helper function for db_rewrite_sql.
  201. *
  202. * Collects JOIN and WHERE statements via hook_db_rewrite_sql()
  203. * Decides whether to select primary_key or DISTINCT(primary_key)
  204. *
  205. * @param $query
  206. * Query to be rewritten.
  207. * @param $primary_table
  208. * Name or alias of the table which has the primary key field for this query. Possible values are: comments, forum, node, menu, term_data, vocabulary.
  209. * @param $primary_field
  210. * Name of the primary field.
  211. * @param $args
  212. * Array of additional arguments.
  213. * @return
  214. * An array: join statements, where statements, field or DISTINCT(field).
  215. */
  216. function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = 'nid', $args = array()) {
  217. $where = array();
  218. $join = array();
  219. $distinct = FALSE;
  220. foreach (module_implements('db_rewrite_sql') as $module) {
  221. $result = module_invoke($module, 'db_rewrite_sql', $query, $primary_table, $primary_field, $args);
  222. if (isset($result) && is_array($result)) {
  223. if (isset($result['where'])) {
  224. $where[] = $result['where'];
  225. }
  226. if (isset($result['join'])) {
  227. $join[] = $result['join'];
  228. }
  229. if (isset($result['distinct']) && $result['distinct']) {
  230. $distinct = TRUE;
  231. }
  232. }
  233. elseif (isset($result)) {
  234. $where[] = $result;
  235. }
  236. }
  237. $where = empty($where) ? '' : '('. implode(') AND (', $where) .')';
  238. $join = empty($join) ? '' : implode(' ', $join);
  239. return array($join, $where, $distinct);
  240. }
  241. /**
  242. * Rewrites node, taxonomy and comment queries. Use it for listing queries. Do not
  243. * use FROM table1, table2 syntax, use JOIN instead.
  244. *
  245. * @param $query
  246. * Query to be rewritten.
  247. * @param $primary_table
  248. * Name or alias of the table which has the primary key field for this query. Possible values are: comments, forum, node, menu, term_data, vocabulary.
  249. * @param $primary_field
  250. * Name of the primary field.
  251. * @param $args
  252. * An array of arguments, passed to the implementations of hook_db_rewrite_sql.
  253. * @return
  254. * The original query with JOIN and WHERE statements inserted from hook_db_rewrite_sql implementations. nid is rewritten if needed.
  255. */
  256. function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) {
  257. list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args);
  258. if ($distinct) {
  259. $query = db_distinct_field($primary_table, $primary_field, $query);
  260. }
  261. if (!empty($where) || !empty($join)) {
  262. if (!empty($where)) {
  263. $new = "WHERE $where ";
  264. }
  265. $new = " $join $new";
  266. if (strpos($query, 'WHERE')) {
  267. $query = str_replace('WHERE', $new .'AND (', $query);
  268. $insert = ') ';
  269. }
  270. else {
  271. $insert = $new;
  272. }
  273. if (strpos($query, 'GROUP')) {
  274. $replace = 'GROUP';
  275. }
  276. elseif (strpos($query, 'ORDER')) {
  277. $replace = 'ORDER';
  278. }
  279. elseif (strpos($query, 'LIMIT')) {
  280. $replace = 'LIMIT';
  281. }
  282. else {
  283. $query .= $insert;
  284. }
  285. if (isset($replace)) {
  286. $query = str_replace($replace, $insert . $replace, $query);
  287. }
  288. }
  289. return $query;
  290. }
  291. /**
  292. * Restrict a dynamic tablename to safe characters.
  293. *
  294. * Only keeps alphanumeric and underscores.
  295. */
  296. function db_escape_table($string) {
  297. return preg_replace('/[^A-Za-z0-9_]+/', '', $string);
  298. }
  299. /**
  300. * @} End of "defgroup database".
  301. */
Login or register to post comments