database.mysqli.inc

  1. drupal
    1. 4.7 includes/database.mysqli.inc
    2. 5 includes/database.mysqli.inc
    3. 6 includes/database.mysqli.inc

Database interface code for MySQL database servers using the mysqli client libraries. mysqli is included in PHP 5 by default and allows developers to use the advanced features of MySQL 4.1.x, 5.0.x and beyond.

Functions & methods

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