database.mysql.inc

Database interface code for MySQL database servers.

File

drupal-6.x/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. // Include functions shared between mysql and mysqli.
  11. require_once './includes/database.mysql-common.inc';
  12. /**
  13. * Report database status.
  14. */
  15. function db_status_report($phase) {
  16. $t = get_t();
  17. $version = db_version();
  18. $form['mysql'] = array(
  19. 'title' => $t('MySQL database'),
  20. 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version,
  21. );
  22. if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) {
  23. $form['mysql']['severity'] = REQUIREMENT_ERROR;
  24. $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL));
  25. }
  26. return $form;
  27. }
  28. /**
  29. * Returns the version of the database server currently in use.
  30. *
  31. * @return Database server version
  32. */
  33. function db_version() {
  34. list($version) = explode('-', mysql_get_server_info());
  35. return $version;
  36. }
  37. /**
  38. * Initialize a database connection.
  39. */
  40. function db_connect($url) {
  41. $url = parse_url($url);
  42. // Check if MySQL support is present in PHP
  43. if (!function_exists('mysql_connect')) {
  44. _db_error_page('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.');
  45. }
  46. // Decode urlencoded information in the db connection string
  47. $url['user'] = urldecode($url['user']);
  48. // Test if database URL has a password.
  49. $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
  50. $url['host'] = urldecode($url['host']);
  51. $url['path'] = urldecode($url['path']);
  52. // Allow for non-standard MySQL port.
  53. if (isset($url['port'])) {
  54. $url['host'] = $url['host'] .':'. $url['port'];
  55. }
  56. // - TRUE makes mysql_connect() always open a new link, even if
  57. // mysql_connect() was called before with the same parameters.
  58. // This is important if you are using two databases on the same
  59. // server.
  60. // - 2 means CLIENT_FOUND_ROWS: return the number of found
  61. // (matched) rows, not the number of affected rows.
  62. $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
  63. if (!$connection || !mysql_select_db(substr($url['path'], 1))) {
  64. // Show error screen otherwise
  65. _db_error_page(mysql_error());
  66. }
  67. // Force MySQL to use the UTF-8 character set. Also set the collation, if a
  68. // certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
  69. // for UTF-8.
  70. if (!empty($GLOBALS['db_collation'])) {
  71. mysql_query('SET NAMES utf8 COLLATE '. $GLOBALS['db_collation'], $connection);
  72. }
  73. else {
  74. mysql_query('SET NAMES utf8', $connection);
  75. }
  76. return $connection;
  77. }
  78. /**
  79. * Helper function for db_query().
  80. */
  81. function _db_query($query, $debug = 0) {
  82. global $active_db, $queries, $user;
  83. if (variable_get('dev_query', 0)) {
  84. list($usec, $sec) = explode(' ', microtime());
  85. $timer = (float)$usec + (float)$sec;
  86. // If devel.module query logging is enabled, prepend a comment with the username and calling function
  87. // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact
  88. // code is issueing the slow query.
  89. $bt = debug_backtrace();
  90. // t() may not be available yet so we don't wrap 'Anonymous'.
  91. $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous');
  92. // str_replace() to prevent SQL injection via username or anonymous name.
  93. $name = str_replace(array('*', '/'), '', $name);
  94. $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query;
  95. }
  96. $result = mysql_query($query, $active_db);
  97. if (variable_get('dev_query', 0)) {
  98. $query = $bt[2]['function'] ."\n". $query;
  99. list($usec, $sec) = explode(' ', microtime());
  100. $stop = (float)$usec + (float)$sec;
  101. $diff = $stop - $timer;
  102. $queries[] = array($query, $diff);
  103. }
  104. if ($debug) {
  105. print '<p>query: '. $query .'<br />error:'. mysql_error($active_db) .'</p>';
  106. }
  107. if (!mysql_errno($active_db)) {
  108. return $result;
  109. }
  110. else {
  111. // Indicate to drupal_error_handler that this is a database error.
  112. ${DB_ERROR} = TRUE;
  113. trigger_error(check_plain(mysql_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
  114. return FALSE;
  115. }
  116. }
  117. /**
  118. * Fetch one result row from the previous query as an object.
  119. *
  120. * @param $result
  121. * A database query result resource, as returned from db_query().
  122. * @return
  123. * An object representing the next row of the result, or FALSE. The attributes
  124. * of this object are the table fields selected by the query.
  125. */
  126. function db_fetch_object($result) {
  127. if ($result) {
  128. return mysql_fetch_object($result);
  129. }
  130. }
  131. /**
  132. * Fetch one result row from the previous query as an array.
  133. *
  134. * @param $result
  135. * A database query result resource, as returned from db_query().
  136. * @return
  137. * An associative array representing the next row of the result, or FALSE.
  138. * The keys of this object are the names of the table fields selected by the
  139. * query, and the values are the field values for this result row.
  140. */
  141. function db_fetch_array($result) {
  142. if ($result) {
  143. return mysql_fetch_array($result, MYSQL_ASSOC);
  144. }
  145. }
  146. /**
  147. * Return an individual result field from the previous query.
  148. *
  149. * Only use this function if exactly one field is being selected; otherwise,
  150. * use db_fetch_object() or db_fetch_array().
  151. *
  152. * @param $result
  153. * A database query result resource, as returned from db_query().
  154. *
  155. * @return
  156. * The resulting field or FALSE.
  157. */
  158. function db_result($result) {
  159. if ($result && mysql_num_rows($result) > 0) {
  160. // The mysql_fetch_row function has an optional second parameter $row
  161. // but that can't be used for compatibility with Oracle, DB2, etc.
  162. $array = mysql_fetch_row($result);
  163. return $array[0];
  164. }
  165. return FALSE;
  166. }
  167. /**
  168. * Determine whether the previous query caused an error.
  169. */
  170. function db_error() {
  171. global $active_db;
  172. return mysql_errno($active_db);
  173. }
  174. /**
  175. * Determine the number of rows changed by the preceding query.
  176. */
  177. function db_affected_rows() {
  178. global $active_db;
  179. return mysql_affected_rows($active_db);
  180. }
  181. /**
  182. * Runs a limited-range query in the active database.
  183. *
  184. * Use this as a substitute for db_query() when a subset of the query is to be
  185. * returned.
  186. * User-supplied arguments to the query should be passed in as separate parameters
  187. * so that they can be properly escaped to avoid SQL injection attacks.
  188. *
  189. * @param $query
  190. * A string containing an SQL query.
  191. * @param ...
  192. * A variable number of arguments which are substituted into the query
  193. * using printf() syntax. The query arguments can be enclosed in one
  194. * array instead.
  195. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  196. * in '') and %%.
  197. *
  198. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  199. * and TRUE values to decimal 1.
  200. *
  201. * @param $from
  202. * The first result row to return.
  203. * @param $count
  204. * The maximum number of result rows to return.
  205. * @return
  206. * A database query result resource, or FALSE if the query was not executed
  207. * correctly.
  208. */
  209. function db_query_range($query) {
  210. $args = func_get_args();
  211. $count = array_pop($args);
  212. $from = array_pop($args);
  213. array_shift($args);
  214. $query = db_prefix_tables($query);
  215. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  216. $args = $args[0];
  217. }
  218. _db_query_callback($args, TRUE);
  219. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  220. $query .= ' LIMIT '. (int)$from .', '. (int)$count;
  221. return _db_query($query);
  222. }
  223. /**
  224. * Runs a SELECT query and stores its results in a temporary table.
  225. *
  226. * Use this as a substitute for db_query() when the results need to be stored
  227. * in a temporary table.
  228. *
  229. * User-supplied arguments to the query should be passed in as separate parameters
  230. * so that they can be properly escaped to avoid SQL injection attacks.
  231. *
  232. * Note that if you need to know how many results were returned, you should do
  233. * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does
  234. * not give consistent result across different database types in this case.
  235. *
  236. * @param $query
  237. * A string containing a normal SELECT SQL query.
  238. * @param ...
  239. * A variable number of arguments which are substituted into the query
  240. * using printf() syntax. The query arguments can be enclosed in one
  241. * array instead.
  242. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  243. * in '') and %%.
  244. *
  245. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  246. * and TRUE values to decimal 1.
  247. * @param $table
  248. * The name of the temporary table to select into. This name will not be
  249. * prefixed as there is no risk of collision.
  250. *
  251. * @return
  252. * A database query result resource, or FALSE if the query was not executed
  253. * correctly.
  254. */
  255. function db_query_temporary($query) {
  256. $args = func_get_args();
  257. $tablename = array_pop($args);
  258. array_shift($args);
  259. $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', db_prefix_tables($query));
  260. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  261. $args = $args[0];
  262. }
  263. _db_query_callback($args, TRUE);
  264. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  265. return _db_query($query);
  266. }
  267. /**
  268. * Returns a properly formatted Binary Large OBject value.
  269. *
  270. * @param $data
  271. * Data to encode.
  272. * @return
  273. * Encoded data.
  274. */
  275. function db_encode_blob($data) {
  276. global $active_db;
  277. return "'". mysql_real_escape_string($data, $active_db) ."'";
  278. }
  279. /**
  280. * Returns text from a Binary Large Object value.
  281. *
  282. * @param $data
  283. * Data to decode.
  284. * @return
  285. * Decoded data.
  286. */
  287. function db_decode_blob($data) {
  288. return $data;
  289. }
  290. /**
  291. * Prepare user input for use in a database query, preventing SQL injection attacks.
  292. */
  293. function db_escape_string($text) {
  294. global $active_db;
  295. return mysql_real_escape_string($text, $active_db);
  296. }
  297. /**
  298. * Lock a table.
  299. */
  300. function db_lock_table($table) {
  301. db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE');
  302. }
  303. /**
  304. * Unlock all locked tables.
  305. */
  306. function db_unlock_tables() {
  307. db_query('UNLOCK TABLES');
  308. }
  309. /**
  310. * Check if a table exists.
  311. *
  312. * @param $table
  313. * The name of the table.
  314. *
  315. * @return
  316. * TRUE if the table exists, and FALSE if the table does not exist.
  317. */
  318. function db_table_exists($table) {
  319. return (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'"));
  320. }
  321. /**
  322. * Check if a column exists in the given table.
  323. *
  324. * @param $table
  325. * The name of the table.
  326. * @param $column
  327. * The name of the column.
  328. *
  329. * @return
  330. * TRUE if the column exists, and FALSE if the column does not exist.
  331. */
  332. function db_column_exists($table, $column) {
  333. return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {". db_escape_table($table) ."} LIKE '". db_escape_table($column) ."'"));
  334. }
  335. /**
  336. * @} End of "ingroup database".
  337. */