database.mysql.inc

  1. drupal
    1. 4.6 includes/database.mysql.inc
    2. 4.7 includes/database.mysql.inc
    3. 5 includes/database.mysql.inc
    4. 6 includes/database.mysql.inc

Database interface code for MySQL database servers.

Functions & methods

NameDescription
db_affected_rowsDetermine the number of rows changed by the preceding query.
db_connectInitialize a database connection.
db_decode_blobReturns text from a Binary Large Object value.
db_distinct_fieldWraps the given table.field entry with a DISTINCT(). The wrapper is added to the SELECT list entry of the given query and the resulting query is returned. This function only applies the wrapper if a DISTINCT doesn't already exist in the query.
db_encode_blobReturns a properly formatted Binary Large OBject value.
db_errorDetermine whether the previous query caused an error.
db_escape_stringPrepare user input for use in a database query, preventing SQL injection attacks.
db_fetch_arrayFetch one result row from the previous query as an array.
db_fetch_objectFetch one result row from the previous query as an object.
db_lock_tableLock a table.
db_next_idReturn a new unique ID in the given sequence.
db_num_rowsDetermine how many result rows were found by the preceding query.
db_query_rangeRuns a limited-range query in the active database.
db_query_temporaryRuns a SELECT query and stores its results in a temporary table.
db_resultReturn an individual result field from the previous query.
db_unlock_tablesUnlock all locked tables.
_db_queryHelper function for db_query().

File

includes/database.mysql.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Database interface code for MySQL database servers.
  5. */
  6. /**
  7. * @ingroup database
  8. * @{
  9. */
  10. /**
  11. * Initialize a database connection.
  12. *
  13. * Note that you can change the mysql_connect() call to mysql_pconnect() if you
  14. * want to use persistent connections. This is not recommended on shared hosts,
  15. * and might require additional database/webserver tuning. It can increase
  16. * performance, however, when the overhead to connect to your database is high
  17. * (e.g. your database and web server live on different machines).
  18. */
  19. function db_connect($url) {
  20. // Check if MySQL support is present in PHP
  21. if (!function_exists('mysql_connect')) {
  22. drupal_maintenance_theme();
  23. drupal_set_title('PHP MySQL support not enabled');
  24. print theme('maintenance_page', '<p>We were unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your <code>PHP.ini</code> to see how you can enable it.</p>
  25. <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>');
  26. exit;
  27. }
  28. $url = parse_url($url);
  29. // Decode url-encoded information in the db connection string
  30. $url['user'] = urldecode($url['user']);
  31. $url['pass'] = urldecode($url['pass']);
  32. $url['host'] = urldecode($url['host']);
  33. $url['path'] = urldecode($url['path']);
  34. // Allow for non-standard MySQL port.
  35. if (isset($url['port'])) {
  36. $url['host'] = $url['host'] .':'. $url['port'];
  37. }
  38. // - TRUE makes mysql_connect() always open a new link, even if
  39. // mysql_connect() was called before with the same parameters.
  40. // This is important if you are using two databases on the same
  41. // server.
  42. // - 2 means CLIENT_FOUND_ROWS: return the number of found
  43. // (matched) rows, not the number of affected rows.
  44. $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
  45. if (!$connection) {
  46. drupal_maintenance_theme();
  47. drupal_set_header('HTTP/1.1 503 Service Unavailable');
  48. drupal_set_title('Unable to connect to database server');
  49. print theme('maintenance_page', '<p>This either means that the username and password information in your <code>settings.php</code> file is incorrect or we can\'t contact the MySQL database server. This could mean your hosting provider\'s database server is down.</p>
  50. <p>The MySQL error was: '. theme('placeholder', mysql_error()) .'.</p>
  51. <p>Currently, the username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.</p>
  52. <ul>
  53. <li>Are you sure you have the correct username and password?</li>
  54. <li>Are you sure that you have typed the correct hostname?</li>
  55. <li>Are you sure that the database server is running?</li>
  56. </ul>
  57. <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>');
  58. exit;
  59. }
  60. if (!mysql_select_db(substr($url['path'], 1))) {
  61. drupal_maintenance_theme();
  62. drupal_set_title('Unable to select database');
  63. print theme('maintenance_page', '<p>We were able to connect to the MySQL database server (which means your username and password are okay) but not able to select the database.</p>
  64. <p>The MySQL error was: '. theme('placeholder', mysql_error($connection)) .'.</p>
  65. <p>Currently, the database is '. theme('placeholder', substr($url['path'], 1)) .'. The username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.</p>
  66. <ul>
  67. <li>Are you sure you have the correct database name?</li>
  68. <li>Are you sure the database exists?</li>
  69. <li>Are you sure the username has permission to access the database?</li>
  70. </ul>
  71. <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>');
  72. exit;
  73. }
  74. /* On MySQL 4.1 and later, force UTF-8 */
  75. if (version_compare(mysql_get_server_info(), '4.1.0', '>=')) {
  76. mysql_query('SET NAMES "utf8"', $connection);
  77. }
  78. return $connection;
  79. }
  80. /**
  81. * Helper function for db_query().
  82. */
  83. function _db_query($query, $debug = 0) {
  84. global $active_db, $queries;
  85. if (variable_get('dev_query', 0)) {
  86. list($usec, $sec) = explode(' ', microtime());
  87. $timer = (float)$usec + (float)$sec;
  88. }
  89. $result = mysql_query($query, $active_db);
  90. if (variable_get('dev_query', 0)) {
  91. $bt = debug_backtrace();
  92. $query = $bt[2]['function'] . "\n" . $query;
  93. list($usec, $sec) = explode(' ', microtime());
  94. $stop = (float)$usec + (float)$sec;
  95. $diff = $stop - $timer;
  96. $queries[] = array($query, $diff);
  97. }
  98. if ($debug) {
  99. print '<p>query: '. $query .'<br />error:'. mysql_error($active_db) .'</p>';
  100. }
  101. if (!mysql_errno($active_db)) {
  102. return $result;
  103. }
  104. else {
  105. trigger_error(check_plain(mysql_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
  106. return FALSE;
  107. }
  108. }
  109. /**
  110. * Fetch one result row from the previous query as an object.
  111. *
  112. * @param $result
  113. * A database query result resource, as returned from db_query().
  114. * @return
  115. * An object representing the next row of the result. The attributes of this
  116. * object are the table fields selected by the query.
  117. */
  118. function db_fetch_object($result) {
  119. if ($result) {
  120. return mysql_fetch_object($result);
  121. }
  122. }
  123. /**
  124. * Fetch one result row from the previous query as an array.
  125. *
  126. * @param $result
  127. * A database query result resource, as returned from db_query().
  128. * @return
  129. * An associative array representing the next row of the result. The keys of
  130. * this object are the names of the table fields selected by the query, and
  131. * the values are the field values for this result row.
  132. */
  133. function db_fetch_array($result) {
  134. if ($result) {
  135. return mysql_fetch_array($result, MYSQL_ASSOC);
  136. }
  137. }
  138. /**
  139. * Determine how many result rows were found by the preceding query.
  140. *
  141. * @param $result
  142. * A database query result resource, as returned from db_query().
  143. * @return
  144. * The number of result rows.
  145. */
  146. function db_num_rows($result) {
  147. if ($result) {
  148. return mysql_num_rows($result);
  149. }
  150. }
  151. /**
  152. * Return an individual result field from the previous query.
  153. *
  154. * Only use this function if exactly one field is being selected; otherwise,
  155. * use db_fetch_object() or db_fetch_array().
  156. *
  157. * @param $result
  158. * A database query result resource, as returned from db_query().
  159. * @param $row
  160. * The index of the row whose result is needed.
  161. * @return
  162. * The resulting field.
  163. */
  164. function db_result($result, $row = 0) {
  165. if ($result && mysql_num_rows($result) > $row) {
  166. return mysql_result($result, $row);
  167. }
  168. }
  169. /**
  170. * Determine whether the previous query caused an error.
  171. */
  172. function db_error() {
  173. global $active_db;
  174. return mysql_errno($active_db);
  175. }
  176. /**
  177. * Return a new unique ID in the given sequence.
  178. *
  179. * For compatibility reasons, Drupal does not use auto-numbered fields in its
  180. * database tables. Instead, this function is used to return a new unique ID
  181. * of the type requested. If necessary, a new sequence with the given name
  182. * will be created.
  183. */
  184. function db_next_id($name) {
  185. $name = db_prefix_tables($name);
  186. db_query('LOCK TABLES {sequences} WRITE');
  187. $id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
  188. db_query("REPLACE INTO {sequences} VALUES ('%s', %d)", $name, $id);
  189. db_query('UNLOCK TABLES');
  190. return $id;
  191. }
  192. /**
  193. * Determine the number of rows changed by the preceding query.
  194. */
  195. function db_affected_rows() {
  196. global $active_db;
  197. return mysql_affected_rows($active_db);
  198. }
  199. /**
  200. * Runs a limited-range query in the active database.
  201. *
  202. * Use this as a substitute for db_query() when a subset of the query is to be
  203. * returned.
  204. * User-supplied arguments to the query should be passed in as separate parameters
  205. * so that they can be properly escaped to avoid SQL injection attacks.
  206. *
  207. * @param $query
  208. * A string containing an SQL query.
  209. * @param ...
  210. * A variable number of arguments which are substituted into the query
  211. * using printf() syntax. The query arguments can be enclosed in one
  212. * array instead.
  213. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  214. * in '') and %%.
  215. *
  216. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  217. * and TRUE values to decimal 1.
  218. *
  219. * @param $from
  220. * The first result row to return.
  221. * @param $count
  222. * The maximum number of result rows to return.
  223. * @return
  224. * A database query result resource, or FALSE if the query was not executed
  225. * correctly.
  226. */
  227. function db_query_range($query) {
  228. $args = func_get_args();
  229. $count = array_pop($args);
  230. $from = array_pop($args);
  231. array_shift($args);
  232. $query = db_prefix_tables($query);
  233. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  234. $args = $args[0];
  235. }
  236. _db_query_callback($args, TRUE);
  237. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  238. $query .= ' LIMIT '. (int)$from .', '. (int)$count;
  239. return _db_query($query);
  240. }
  241. /**
  242. * Runs a SELECT query and stores its results in a temporary table.
  243. *
  244. * Use this as a substitute for db_query() when the results need to stored
  245. * in a temporary table. Temporary tables exist for the duration of the page
  246. * request.
  247. * User-supplied arguments to the query should be passed in as separate parameters
  248. * so that they can be properly escaped to avoid SQL injection attacks.
  249. *
  250. * Note that if you need to know how many results were returned, you should do
  251. * a SELECT COUNT(*) on the temporary table afterwards. db_num_rows() and
  252. * db_affected_rows() do not give consistent result across different database
  253. * types in this case.
  254. *
  255. * @param $query
  256. * A string containing a normal SELECT SQL query.
  257. * @param ...
  258. * A variable number of arguments which are substituted into the query
  259. * using printf() syntax. The query arguments can be enclosed in one
  260. * array instead.
  261. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  262. * in '') and %%.
  263. *
  264. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  265. * and TRUE values to decimal 1.
  266. *
  267. * @param $table
  268. * The name of the temporary table to select into. This name will not be
  269. * prefixed as there is no risk of collision.
  270. * @return
  271. * A database query result resource, or FALSE if the query was not executed
  272. * correctly.
  273. */
  274. function db_query_temporary($query) {
  275. $args = func_get_args();
  276. $tablename = array_pop($args);
  277. array_shift($args);
  278. $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' SELECT', db_prefix_tables($query));
  279. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  280. $args = $args[0];
  281. }
  282. _db_query_callback($args, TRUE);
  283. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  284. return _db_query($query);
  285. }
  286. /**
  287. * Returns a properly formatted Binary Large OBject value.
  288. *
  289. * @param $data
  290. * Data to encode.
  291. * @return
  292. * Encoded data.
  293. */
  294. function db_encode_blob($data) {
  295. global $active_db;
  296. return "'" . mysql_real_escape_string($data, $active_db) . "'";
  297. }
  298. /**
  299. * Returns text from a Binary Large Object value.
  300. *
  301. * @param $data
  302. * Data to decode.
  303. * @return
  304. * Decoded data.
  305. */
  306. function db_decode_blob($data) {
  307. return $data;
  308. }
  309. /**
  310. * Prepare user input for use in a database query, preventing SQL injection attacks.
  311. */
  312. function db_escape_string($text) {
  313. global $active_db;
  314. return mysql_real_escape_string($text, $active_db);
  315. }
  316. /**
  317. * Lock a table.
  318. */
  319. function db_lock_table($table) {
  320. db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE');
  321. }
  322. /**
  323. * Unlock all locked tables.
  324. */
  325. function db_unlock_tables() {
  326. db_query('UNLOCK TABLES');
  327. }
  328. /**
  329. * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
  330. * the SELECT list entry of the given query and the resulting query is returned.
  331. * This function only applies the wrapper if a DISTINCT doesn't already exist in
  332. * the query.
  333. *
  334. * @param $table Table containing the field to set as DISTINCT
  335. * @param $field Field to set as DISTINCT
  336. * @param $query Query to apply the wrapper to
  337. * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
  338. */
  339. function db_distinct_field($table, $field, $query) {
  340. $field_to_select = 'DISTINCT('. $table .'.'. $field .')';
  341. // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
  342. return preg_replace('/(SELECT.*)('. $table .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query);
  343. }
  344. /**
  345. * @} End of "ingroup database".
  346. */
Login or register to post comments