home *** CD-ROM | disk | FTP | other *** search
/ PCGUIA 117 / PC Guia 117.iso / Software / Produtividade / Software2 / Product4 / Setup.exe / drupal-4.6.0 / includes / database.inc < prev    next >
Encoding:
Text File  |  2005-04-08  |  9.0 KB  |  286 lines

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