PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/package/wpmu/2.9.2/wordpress-mu/wp-includes/wp-db/sqlsrv/sqlsrv.php

https://github.com/wpms/wp-sqlsrv
PHP | 1340 lines | 686 code | 122 blank | 532 comment | 110 complexity | ee969f6556cd7d9f2949ea3e0c5d5434 MD5 | raw file
  1. <?php
  2. /**
  3. * WordPress DB Class
  4. *
  5. * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
  6. *
  7. * Modifications for SQLSRV (Microsoft PHP SQL Server driver) by A.Garcia and A.Gentile
  8. *
  9. * @package WordPress
  10. * @subpackage Database
  11. * @since 0.71
  12. */
  13. /**
  14. * @since 0.71
  15. */
  16. define('EZSQL_VERSION', 'WP1.25');
  17. /**
  18. * @since 0.71
  19. */
  20. define('OBJECT', 'OBJECT', true);
  21. /**
  22. * @since {@internal Version Unknown}}
  23. */
  24. define('OBJECT_K', 'OBJECT_K', false);
  25. /**
  26. * @since 0.71
  27. */
  28. define('ARRAY_A', 'ARRAY_A', false);
  29. /**
  30. * @since 0.71
  31. */
  32. define('ARRAY_N', 'ARRAY_N', false);
  33. require_once 'translations/translations.php';
  34. /**
  35. * WordPress Database Access Abstraction Object
  36. *
  37. * It is possible to replace this class with your own
  38. * by setting the $wpdb global variable in wp-content/db.php
  39. * file with your class. You can name it wpdb also, since
  40. * this file will not be included, if the other file is
  41. * available.
  42. *
  43. * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
  44. *
  45. * @package WordPress
  46. * @subpackage Database
  47. * @since 0.71
  48. * @final
  49. */
  50. class wpdb extends SQL_Translations {
  51. /**
  52. * Whether to show SQL/DB errors
  53. *
  54. * @since 0.71
  55. * @access private
  56. * @var bool
  57. */
  58. var $show_errors = true;
  59. /**
  60. * Whether to suppress errors during the DB bootstrapping.
  61. *
  62. * @access private
  63. * @since {@internal Version Unknown}}
  64. * @var bool
  65. */
  66. var $suppress_errors = false;
  67. /**
  68. * The last error during query.
  69. *
  70. * @since {@internal Version Unknown}}
  71. * @var string
  72. */
  73. var $last_error = '';
  74. /**
  75. * Amount of queries made
  76. *
  77. * @since 1.2.0
  78. * @access private
  79. * @var int
  80. */
  81. var $num_queries = 0;
  82. /**
  83. * Saved result of the last query made
  84. *
  85. * @since 1.2.0
  86. * @access private
  87. * @var array
  88. */
  89. var $last_query;
  90. /**
  91. * Saved info on the table column
  92. *
  93. * @since 1.2.0
  94. * @access private
  95. * @var array
  96. */
  97. var $col_info;
  98. /**
  99. * Saved queries that were executed
  100. *
  101. * @since 1.5.0
  102. * @access private
  103. * @var array
  104. */
  105. var $queries;
  106. /**
  107. * WordPress table prefix
  108. *
  109. * You can set this to have multiple WordPress installations
  110. * in a single database. The second reason is for possible
  111. * security precautions.
  112. *
  113. * @since 0.71
  114. * @access private
  115. * @var string
  116. */
  117. var $prefix = '';
  118. /**
  119. * Whether the database queries are ready to start executing.
  120. *
  121. * @since 2.5.0
  122. * @access private
  123. * @var bool
  124. */
  125. var $ready = false;
  126. var $blogid = 0;
  127. var $siteid = 0;
  128. var $blogs;
  129. var $signups;
  130. var $site;
  131. var $sitemeta;
  132. var $sitecategories;
  133. var $global_tables = array('blogs', 'signups', 'site', 'sitemeta', 'users', 'usermeta', 'sitecategories', 'registration_log', 'blog_versions');
  134. /**
  135. * WordPress Posts table
  136. *
  137. * @since 1.5.0
  138. * @access public
  139. * @var string
  140. */
  141. var $posts;
  142. /**
  143. * WordPress Users table
  144. *
  145. * @since 1.5.0
  146. * @access public
  147. * @var string
  148. */
  149. var $users;
  150. /**
  151. * WordPress Categories table
  152. *
  153. * @since 1.5.0
  154. * @access public
  155. * @var string
  156. */
  157. var $categories;
  158. /**
  159. * WordPress Post to Category table
  160. *
  161. * @since 1.5.0
  162. * @access public
  163. * @var string
  164. */
  165. var $post2cat;
  166. /**
  167. * WordPress Comments table
  168. *
  169. * @since 1.5.0
  170. * @access public
  171. * @var string
  172. */
  173. var $comments;
  174. /**
  175. * WordPress Links table
  176. *
  177. * @since 1.5.0
  178. * @access public
  179. * @var string
  180. */
  181. var $links;
  182. /**
  183. * WordPress Options table
  184. *
  185. * @since 1.5.0
  186. * @access public
  187. * @var string
  188. */
  189. var $options;
  190. /**
  191. * WordPress Post Metadata table
  192. *
  193. * @since {@internal Version Unknown}}
  194. * @access public
  195. * @var string
  196. */
  197. var $postmeta;
  198. /**
  199. * WordPress Comment Metadata table
  200. *
  201. * @since 2.9
  202. * @access public
  203. * @var string
  204. */
  205. var $commentmeta;
  206. /**
  207. * WordPress User Metadata table
  208. *
  209. * @since 2.3.0
  210. * @access public
  211. * @var string
  212. */
  213. var $usermeta;
  214. /**
  215. * WordPress Terms table
  216. *
  217. * @since 2.3.0
  218. * @access public
  219. * @var string
  220. */
  221. var $terms;
  222. /**
  223. * WordPress Term Taxonomy table
  224. *
  225. * @since 2.3.0
  226. * @access public
  227. * @var string
  228. */
  229. var $term_taxonomy;
  230. /**
  231. * WordPress Term Relationships table
  232. *
  233. * @since 2.3.0
  234. * @access public
  235. * @var string
  236. */
  237. var $term_relationships;
  238. /**
  239. * List of WordPress tables
  240. *
  241. * @since {@internal Version Unknown}}
  242. * @access private
  243. * @var array
  244. */
  245. var $tables = array('posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options',
  246. 'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta');
  247. /**
  248. * List of deprecated WordPress tables
  249. *
  250. * @since 2.9.0
  251. * @access private
  252. * @var array
  253. */
  254. var $old_tables = array('categories', 'post2cat', 'link2cat');
  255. /**
  256. * Format specifiers for DB columns. Columns not listed here default to %s. Initialized in wp-settings.php.
  257. *
  258. * Keys are colmn names, values are format types: 'ID' => '%d'
  259. *
  260. * @since 2.8.0
  261. * @see wpdb:prepare()
  262. * @see wpdb:insert()
  263. * @see wpdb:update()
  264. * @access public
  265. * @war array
  266. */
  267. var $field_types = array();
  268. /**
  269. * Database table columns charset
  270. *
  271. * @since 2.2.0
  272. * @access public
  273. * @var string
  274. */
  275. var $charset;
  276. /**
  277. * Database table columns collate
  278. *
  279. * @since 2.2.0
  280. * @access public
  281. * @var string
  282. */
  283. var $collate;
  284. /**
  285. * Whether to use mysql_real_escape_string
  286. *
  287. * @since 2.8.0
  288. * @access public
  289. * @var bool
  290. */
  291. var $real_escape = false;
  292. /**
  293. * Saved result of the last translated query made
  294. *
  295. * @since 1.2.0
  296. * @access private
  297. * @var array
  298. */
  299. var $previous_query;
  300. /**
  301. * Database type
  302. * @access public
  303. * @var string
  304. */
  305. var $db_type;
  306. /**
  307. * Database Username
  308. *
  309. * @since 2.9.0
  310. * @access private
  311. * @var string
  312. */
  313. var $dbuser;
  314. /**
  315. * Connects to the database server and selects a database
  316. *
  317. * PHP4 compatibility layer for calling the PHP5 constructor.
  318. *
  319. * @uses wpdb::__construct() Passes parameters and returns result
  320. * @since 0.71
  321. *
  322. * @param string $dbtype database type
  323. * @param string $dbuser database user
  324. * @param string $dbpassword database password
  325. * @param string $dbname database name
  326. * @param string $dbhost database host
  327. */
  328. function wpdb($dbuser, $dbpassword, $dbname, $dbhost) {
  329. if( defined( "WP_USE_MULTIPLE_DB" ) && CONSTANT( "WP_USE_MULTIPLE_DB" ) == true )
  330. $this->db_connect();
  331. return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost);
  332. }
  333. /**
  334. * Connects to the database server and selects a database
  335. *
  336. * PHP5 style constructor for compatibility with PHP5. Does
  337. * the actual setting up of the class properties and connection
  338. * to the database.
  339. *
  340. * @since 2.0.8
  341. *
  342. * @param string $dbtype database type
  343. * @param string $dbuser database user
  344. * @param string $dbpassword database password
  345. * @param string $dbname database name
  346. * @param string $dbhost database host
  347. */
  348. function __construct($dbuser, $dbpassword, $dbname, $dbhost) {
  349. register_shutdown_function(array(&$this, "__destruct"));
  350. if ( defined('WP_DEBUG') and WP_DEBUG == true ) {
  351. $this->show_errors();
  352. }
  353. $this->charset = 'utf8';
  354. if( defined( 'DB_COLLATE' ) && constant( 'DB_COLLATE' ) != '' ) {
  355. $this->collate = constant( 'DB_COLLATE' );
  356. } else {
  357. $this->collate = 'utf8_general_ci';
  358. }
  359. if ( defined('DB_CHARSET') ) {
  360. $this->charset = DB_CHARSET;
  361. }
  362. if ( defined('DB_COLLATE') ) {
  363. $this->collate = DB_COLLATE;
  364. }
  365. parent::__construct();
  366. $this->db_type = DB_TYPE;
  367. if (get_magic_quotes_gpc()) {
  368. $dbhost = trim(str_replace("\\\\", "\\", $dbhost));
  369. }
  370. /* Specify the server and connection string attributes. */
  371. $connection_info = array(
  372. 'UID' => $dbuser,
  373. 'PWD' => $dbpassword,
  374. 'Database' => $dbname,
  375. );
  376. // Is this SQL Azure?
  377. if (stristr($dbhost, 'database.windows.net') !== false) {
  378. // Need to turn off MultipleActiveResultSets, this requires
  379. // Sql Server Driver for PHP 1.1 (1.0 doesn't support this property)
  380. $connection_info['MultipleActiveResultSets'] = false;
  381. $this->azure = true;
  382. }
  383. $this->dbh = sqlsrv_connect( $dbhost, $connection_info);
  384. sqlsrv_configure('WarningsReturnAsErrors', 1);
  385. if (!$this->dbh) {
  386. $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/"
  387. <h1>Error establishing a database connection</h1>
  388. <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p>
  389. <ul>
  390. <li>Are you sure you have the correct username and password?</li>
  391. <li>Are you sure that you have typed the correct hostname?</li>
  392. <li>Are you sure that the database server is running?</li>
  393. </ul>
  394. <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
  395. "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost));
  396. return;
  397. }
  398. $this->ready = true;
  399. // Make sure textsize fields are set to max.
  400. @sqlsrv_query('SET TEXTSIZE 2147483647');
  401. /* SET NAMES doesn't translate
  402. if ( $this->supports_collation() ) {
  403. $collation_query = '';
  404. if ( !empty($this->charset) ) {
  405. $collation_query = "SET NAMES '{$this->charset}'";
  406. if (!empty($this->collate) )
  407. $collation_query .= " COLLATE '{$this->collate}'";
  408. }
  409. if ( !empty($collation_query) )
  410. $this->query($collation_query);
  411. }
  412. */
  413. $this->select($dbname);
  414. }
  415. /**
  416. * PHP5 style destructor and will run when database object is destroyed.
  417. *
  418. * @since 2.0.8
  419. *
  420. * @return bool Always true
  421. */
  422. function __destruct() {
  423. if ( $this->dbh ) {
  424. sqlsrv_close( $this->dbh );
  425. }
  426. return true;
  427. }
  428. /**
  429. * Sets the table prefix for the WordPress tables.
  430. *
  431. * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
  432. * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix.
  433. *
  434. * @since 2.5.0
  435. *
  436. * @param string $prefix Alphanumeric name for the new prefix.
  437. * @return string|WP_Error Old prefix or WP_Error on error
  438. */
  439. function set_prefix($prefix) {
  440. if ( preg_match('|[^a-z0-9_]|i', $prefix) )
  441. return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/);
  442. $old_prefix = '';
  443. if( isset( $this->base_prefix ) )
  444. $old_prefix = $this->base_prefix;
  445. $this->base_prefix = $prefix;
  446. foreach ( $this->global_tables as $table )
  447. $this->$table = $prefix . $table;
  448. if ( empty($this->blogid) )
  449. return $old_prefix;
  450. $this->prefix = $this->get_blog_prefix( $this->blogid );
  451. foreach ( (array) $this->tables as $table )
  452. $this->$table = $this->prefix . $table;
  453. if ( defined('CUSTOM_USER_TABLE') )
  454. $this->users = CUSTOM_USER_TABLE;
  455. if ( defined('CUSTOM_USER_META_TABLE') )
  456. $this->usermeta = CUSTOM_USER_META_TABLE;
  457. return $old_prefix;
  458. }
  459. function set_blog_id($blog_id, $site_id = '') {
  460. if ( !empty($site_id) )
  461. $this->siteid = $site_id;
  462. $old_blog_id = $this->blogid;
  463. $this->blogid = $blog_id;
  464. $this->prefix = $this->get_blog_prefix( $this->blogid );
  465. foreach ( $this->tables as $table )
  466. $this->$table = $this->prefix . $table;
  467. return $old_blog_id;
  468. }
  469. function get_blog_prefix( $blog_id = '' ) {
  470. if ( $blog_id ) {
  471. return $this->base_prefix . $blog_id . '_';
  472. } else {
  473. return $this->prefix;
  474. }
  475. }
  476. /**
  477. * Selects a database using the current database connection.
  478. *
  479. * The database name will be changed based on the current database
  480. * connection. On failure, the execution will bail and display an DB error.
  481. *
  482. * @since 0.71
  483. *
  484. * @param string $db database name
  485. * @return null Always null.
  486. */
  487. function select($db) {
  488. $result = $this->dbh;
  489. if (!$result) {
  490. $this->ready = false;
  491. $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/'
  492. <h1>Can&#8217;t select database</h1>
  493. <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
  494. <ul>
  495. <li>Are you sure it exists?</li>
  496. <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
  497. <li>On some systems the name of your database is prefixed with your username, so it would be like username_wordpress. Could that be the problem?</li>
  498. </ul>
  499. <p>If you don\'t know how to setup a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>'/*/WP_I18N_DB_SELECT_DB*/, $db, DB_USER));
  500. return;
  501. }
  502. }
  503. /**
  504. * Escapes content for insertion into the database, for security
  505. *
  506. * @since 0.71
  507. *
  508. * @param string $string
  509. * @return string query safe string
  510. */
  511. function escape($string) {
  512. return str_replace("'", "''", $string);
  513. }
  514. /**
  515. * Escapes content by reference for insertion into the database, for security
  516. *
  517. * @since 2.3.0
  518. *
  519. * @param string $s
  520. */
  521. function escape_by_ref(&$s) {
  522. $s = $this->escape($s);
  523. }
  524. /**
  525. * Prepares a SQL query for safe use, using sprintf() syntax.
  526. *
  527. * @link http://php.net/sprintf See for syntax to use for query string.
  528. * @since 2.3.0
  529. *
  530. * @param null|string $args If string, first parameter must be query statement
  531. * @param mixed $args,... If additional parameters, they will be set inserted into the query.
  532. * @return null|string Sanitized query string
  533. */
  534. function prepare($query = null) {
  535. if ( is_null( $query ) ) {
  536. return;
  537. }
  538. $this->prepare_args = func_get_args();
  539. array_shift($this->prepare_args);
  540. // If args were passed as an array (as in vsprintf), move them up
  541. if ( isset($this->prepare_args[0]) && is_array($this->prepare_args[0]) ) {
  542. $this->prepare_args = $this->prepare_args[0];
  543. }
  544. $flag = '--PREPARE';
  545. foreach($this->prepare_args as $key => $arg){
  546. if ($key !== 0 && is_serialized($arg)) {
  547. $flag = '--SERIALIZED';
  548. }
  549. }
  550. $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
  551. $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
  552. $query = str_replace('%s', "'%s'", $query); // quote the strings
  553. array_walk($this->prepare_args, array(&$this, 'escape_by_ref'));
  554. return @vsprintf($query, $this->prepare_args).$flag;
  555. }
  556. /**
  557. * Print SQL/DB error.
  558. *
  559. * @since 0.71
  560. * @global array $EZSQL_ERROR Stores error information of query and error string
  561. *
  562. * @param string $str The error to display
  563. * @return bool False if the showing of errors is disabled.
  564. */
  565. function print_error($str = '') {
  566. global $EZSQL_ERROR;
  567. if (!$str) {
  568. $str = sqlsrv_errors(SQLSRV_ERR_ALL);
  569. }
  570. $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
  571. if ( $this->suppress_errors )
  572. return false;
  573. if ( $caller = $this->get_caller() )
  574. $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR_FULL*/'WordPress database error %1$s for query %2$s made by %3$s'/*/WP_I18N_DB_QUERY_ERROR_FULL*/, $str, $this->last_query, $caller);
  575. else
  576. $error_str = sprintf(/*WP_I18N_DB_QUERY_ERROR*/'WordPress database error %1$s for query %2$s'/*/WP_I18N_DB_QUERY_ERROR*/, $str, $this->last_query);
  577. $log_error = true;
  578. if ( ! function_exists('error_log') )
  579. $log_error = false;
  580. $log_file = @ini_get('error_log');
  581. if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
  582. $log_error = false;
  583. if ( $log_error )
  584. @error_log($error_str, 0);
  585. // Is error output turned on or not..
  586. if ( !$this->show_errors )
  587. return false;
  588. // If there is an error then take note of it
  589. $msg = "WordPress database error: [$str]\n{$this->query}\n";
  590. if( defined( 'ERRORLOGFILE' ) )
  591. error_log( $msg, 3, CONSTANT( 'ERRORLOGFILE' ) );
  592. if( defined( 'DIEONDBERROR' ) )
  593. die( $msg );
  594. }
  595. /**
  596. * Enables showing of database errors.
  597. *
  598. * This function should be used only to enable showing of errors.
  599. * wpdb::hide_errors() should be used instead for hiding of errors. However,
  600. * this function can be used to enable and disable showing of database
  601. * errors.
  602. *
  603. * @since 0.71
  604. *
  605. * @param bool $show Whether to show or hide errors
  606. * @return bool Old value for showing errors.
  607. */
  608. function show_errors( $show = true ) {
  609. $errors = $this->show_errors;
  610. $this->show_errors = $show;
  611. return $errors;
  612. }
  613. /**
  614. * Disables showing of database errors.
  615. *
  616. * @since 0.71
  617. *
  618. * @return bool Whether showing of errors was active or not
  619. */
  620. function hide_errors() {
  621. $show = $this->show_errors;
  622. $this->show_errors = false;
  623. return $show;
  624. }
  625. /**
  626. * Whether to suppress database errors.
  627. *
  628. * @param unknown_type $suppress
  629. * @return unknown
  630. */
  631. function suppress_errors( $suppress = true ) {
  632. $errors = $this->suppress_errors;
  633. $this->suppress_errors = $suppress;
  634. return $errors;
  635. }
  636. /**
  637. * Kill cached query results.
  638. *
  639. * @since 0.71
  640. */
  641. function flush() {
  642. $this->last_result = array();
  643. $this->col_info = null;
  644. $this->last_query = null;
  645. }
  646. function db_connect( $query = "SELECT" ) {
  647. global $db_list, $global_db_list;
  648. if( is_array( $db_list ) == false )
  649. return true;
  650. if( $this->blogs != '' && preg_match("/(" . $this->blogs . "|" . $this->users . "|" . $this->usermeta . "|" . $this->site . "|" . $this->sitemeta . "|" . $this->sitecategories . ")/i",$query) ) {
  651. $action = 'global';
  652. $details = $global_db_list[ mt_rand( 0, count( $global_db_list ) -1 ) ];
  653. $this->db_global = $details;
  654. } elseif ( preg_match("/^\\s*(alter table|create|insert|delete|update|replace) /i",$query) ) {
  655. $action = 'write';
  656. $details = $db_list[ 'write' ][ mt_rand( 0, count( $db_list[ 'write' ] ) -1 ) ];
  657. $this->db_write = $details;
  658. } else {
  659. $action = '';
  660. $details = $db_list[ 'read' ][ mt_rand( 0, count( $db_list[ 'read' ] ) -1 ) ];
  661. $this->db_read = $details;
  662. }
  663. $dbhname = "dbh" . $action;
  664. if (get_magic_quotes_gpc()) {
  665. $details[ 'db_host' ] = trim(str_replace("\\\\", "\\", $details[ 'db_host' ]));
  666. }
  667. /* Specify the server and connection string attributes. */
  668. $connection_info = array(
  669. 'UID' => $details[ 'db_user' ],
  670. 'PWD' => $details[ 'db_password' ],
  671. 'Database' => $details[ 'db_name' ],
  672. );
  673. // Is this SQL Azure?
  674. if (stristr($details[ 'db_host' ], 'database.windows.net') !== false) {
  675. // Need to turn off MultipleActiveResultSets, this requires
  676. // Sql Server Driver for PHP 1.1 (1.0 doesn't support this property)
  677. $connection_info['MultipleActiveResultSets'] = false;
  678. $this->azure = true;
  679. }
  680. $this->$dbhname = sqlsrv_connect( $details[ 'db_host' ], $connection_info);
  681. sqlsrv_configure('WarningsReturnAsErrors', 1);
  682. if (!$this->$dbhname ) {
  683. $this->bail("
  684. <h1>Error establishing a database connection</h1>
  685. <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>$dbhost</code>. This could mean your host's database server is down.</p>
  686. <ul>
  687. <li>Are you sure you have the correct username and password?</li>
  688. <li>Are you sure that you have typed the correct hostname?</li>
  689. <li>Are you sure that the database server is running?</li>
  690. </ul>
  691. <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p>
  692. ");
  693. }
  694. }
  695. /**
  696. * Perform a SQLSRV database query, using current database connection.
  697. *
  698. * More information can be found on the codex page.
  699. *
  700. * @since 0.71
  701. *
  702. * @param string $query
  703. * @param bool $translate Should we translate the query?
  704. * @return int|false Number of rows affected/selected or false on error
  705. */
  706. function query($query, $translate = true) {
  707. if ( ! $this->ready ) {
  708. return false;
  709. }
  710. // filter the query, if filters are available
  711. // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method
  712. if ( function_exists('apply_filters') ) {
  713. $query = apply_filters('query', $query);
  714. }
  715. // initialise return
  716. $return_val = 0;
  717. $this->flush();
  718. // Log how the function was called
  719. $this->func_call = "\$db->query(\"$query\")";
  720. // Keep track of the last query for debug..
  721. $this->last_query = $query;
  722. // use $this->dbh for read ops, and $this->dbhwrite for write ops
  723. // use $this->dbhglobal for gloal table ops
  724. unset( $dbh );
  725. if( defined( "WP_USE_MULTIPLE_DB" ) && CONSTANT( "WP_USE_MULTIPLE_DB" ) == true ) {
  726. if( $this->blogs != '' && preg_match("/(" . $this->blogs . "|" . $this->users . "|" . $this->usermeta . "|" . $this->site . "|" . $this->sitemeta . "|" . $this->sitecategories . ")/i",$query) ) {
  727. if( false == isset( $this->dbhglobal ) ) {
  728. $this->db_connect( $query );
  729. }
  730. $dbh =& $this->dbhglobal;
  731. $this->last_db_used = "global";
  732. } elseif ( preg_match("/^\\s*(alter table|create|insert|delete|update|replace) /i",$query) ) {
  733. if( false == isset( $this->dbhwrite ) ) {
  734. $this->db_connect( $query );
  735. }
  736. $dbh =& $this->dbhwrite;
  737. $this->last_db_used = "write";
  738. } else {
  739. $dbh =& $this->dbh;
  740. $this->last_db_used = "read";
  741. }
  742. } else {
  743. $dbh =& $this->dbh;
  744. $this->last_db_used = "other/read";
  745. }
  746. // Make Necessary Translations
  747. if ($translate === true) {
  748. $query = $this->translate($query);
  749. $this->previous_query = $query;
  750. }
  751. if ($this->preceeding_query !== false) {
  752. if (is_array($this->preceeding_query)) {
  753. foreach ($this->preceeding_query as $p_query) {
  754. @sqlsrv_query($dbh, $p_query);
  755. }
  756. } else {
  757. @sqlsrv_query($dbh, $this->preceeding_query);
  758. }
  759. $this->preceeding_query = false;
  760. }
  761. // Check if array of queries (this happens for INSERTS with multiple VALUES blocks)
  762. if (is_array($query)) {
  763. foreach ($query as $sub_query) {
  764. $this->_pre_query();
  765. $this->result = @sqlsrv_query($dbh, $sub_query);
  766. $return_val = $this->_post_query($dbh, $sub_query);
  767. }
  768. } else {
  769. $this->_pre_query();
  770. $this->result = @sqlsrv_query($dbh, $query);
  771. $return_val = $this->_post_query($dbh, $query);
  772. }
  773. if ($this->following_query !== false) {
  774. if (is_array($this->following_query)) {
  775. foreach ($this->following_query as $f_query) {
  776. @sqlsrv_query($dbh, $f_query);
  777. }
  778. } else {
  779. @sqlsrv_query($dbh, $this->following_query);
  780. }
  781. $this->following_query = false;
  782. }
  783. return $return_val;
  784. }
  785. function _pre_query() {
  786. if ( defined('SAVEQUERIES') && SAVEQUERIES ) {
  787. $this->timer_start();
  788. }
  789. }
  790. function _post_query($dbh, $query) {
  791. ++$this->num_queries;
  792. if ( defined('SAVEQUERIES') && SAVEQUERIES ) {
  793. $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
  794. }
  795. // If there is an error then take note of it..
  796. if ( $this->result == FALSE ) {
  797. $this->last_error = sqlsrv_errors(SQLSRV_ERR_ALL);
  798. if ($this->last_error != '') {
  799. //echo "<pre>";
  800. //var_dump($query);
  801. //var_dump($this->translation_changes);
  802. //echo "</pre>";
  803. $this->print_error();
  804. }
  805. return false;
  806. }
  807. if ( preg_match("/^\\s*(insert|delete|update|replace) /i",$query) ) {
  808. $this->rows_affected = sqlsrv_rows_affected($this->result);
  809. // Take note of the insert_id
  810. if ( preg_match("/^\\s*(insert|replace) /i",$query) ) {
  811. $result = @sqlsrv_fetch_object(@sqlsrv_query($dbh, "SELECT SCOPE_IDENTITY() AS ID"));
  812. $this->insert_id = $result->ID;
  813. }
  814. $return_val = $this->rows_affected;
  815. } else {
  816. $i = 0;
  817. while ($i < @sqlsrv_num_fields($this->result)) {
  818. $field = @sqlsrv_field_metadata($this->result);
  819. if ($field[0]['Type'] == -1) {
  820. $type = 'text';
  821. } elseif ($field[0]['Type'] == 12) {
  822. $type = 'char';
  823. } elseif ($field[0]['Type'] == -5) {
  824. $type = 'numeric';
  825. } else {
  826. $type = $field[0]['Type'];
  827. }
  828. $new_field = new stdClass();
  829. $new_field->name = $field[0]['Name'];
  830. $new_field->table = $field[0]['Name'];
  831. $new_field->def = null;
  832. $new_field->max_length = $field[0]['Size'];
  833. $new_field->not_null = true;
  834. $new_field->primary_key = null;
  835. $new_field->unique_key = null;
  836. $new_field->multiple_key = null;
  837. $new_field->numeric = $field[0]['Precision'];
  838. $new_field->blob = null;
  839. $new_field->type = $type;
  840. $new_field->unsigned = null;
  841. $new_field->zerofill = null;
  842. $this->col_info[$i] = $new_field;
  843. $i++;
  844. }
  845. $num_rows = 0;
  846. while ( $row = @sqlsrv_fetch_object($this->result) ) {
  847. $this->last_result[$num_rows] = $row;
  848. $num_rows++;
  849. }
  850. $this->last_result = $this->fix_results($this->last_result);
  851. // perform limit
  852. if (!empty($this->limit)) {
  853. $this->last_result = array_slice($this->last_result, $this->limit['from'], $this->limit['to']);
  854. $num_rows = count($this->last_result);
  855. }
  856. @sqlsrv_free_stmt($this->result);
  857. // Log number of rows the query returned
  858. $this->num_rows = $num_rows;
  859. // Return number of rows selected
  860. $return_val = $this->num_rows;
  861. }
  862. return $return_val;
  863. }
  864. /**
  865. * Insert a row into a table.
  866. *
  867. * <code>
  868. * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
  869. * </code>
  870. *
  871. * @since 2.5.0
  872. * @see wpdb::prepare()
  873. *
  874. * @param string $table table name
  875. * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  876. * @param array|string $format (optional) An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings.
  877. * @return int|false The number of rows inserted, or false on error.
  878. */
  879. function insert($table, $data, $format = null) {
  880. $formats = $format = (array) $format;
  881. $fields = array_keys($data);
  882. $formatted_fields = array();
  883. foreach ( $fields as $field ) {
  884. if ( !empty($format) )
  885. $form = ( $form = array_shift($formats) ) ? $form : $format[0];
  886. elseif ( isset($this->field_types[$field]) )
  887. $form = $this->field_types[$field];
  888. else
  889. $form = '%s';
  890. $formatted_fields[] = $form;
  891. }
  892. $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
  893. return $this->query( $this->prepare( $sql, $data) );
  894. }
  895. /**
  896. * Update a row in the table
  897. *
  898. * <code>
  899. * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
  900. * </code>
  901. *
  902. * @since 2.5.0
  903. * @see wpdb::prepare()
  904. *
  905. * @param string $table table name
  906. * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  907. * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw".
  908. * @param array|string $format (optional) An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $data will be treated as strings.
  909. * @param array|string $format_where (optional) An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%s' (decimal number, string). If omitted, all values in $where will be treated as strings.
  910. * @return int|false The number of rows updated, or false on error.
  911. */
  912. function update($table, $data, $where, $format = null, $where_format = null) {
  913. if ( !is_array( $where ) )
  914. return false;
  915. $formats = $format = (array) $format;
  916. $bits = $wheres = array();
  917. foreach ( (array) array_keys($data) as $field ) {
  918. if ( !empty($format) )
  919. $form = ( $form = array_shift($formats) ) ? $form : $format[0];
  920. elseif ( isset($this->field_types[$field]) )
  921. $form = $this->field_types[$field];
  922. else
  923. $form = '%s';
  924. $bits[] = "`$field` = {$form}";
  925. }
  926. $where_formats = $where_format = (array) $where_format;
  927. foreach ( (array) array_keys($where) as $field ) {
  928. if ( !empty($where_format) )
  929. $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
  930. elseif ( isset($this->field_types[$field]) )
  931. $form = $this->field_types[$field];
  932. else
  933. $form = '%s';
  934. $wheres[] = "`$field` = {$form}";
  935. }
  936. $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
  937. return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
  938. }
  939. /**
  940. * Retrieve one variable from the database.
  941. *
  942. * This combines the functionality of wpdb::get_row() and wpdb::get_col(),
  943. * so both the column and row can be picked.
  944. *
  945. * It is possible to use this function without executing more queries. If
  946. * you already made a query, you can set the $query to 'null' value and just
  947. * retrieve either the column and row of the last query result.
  948. *
  949. * @since 0.71
  950. *
  951. * @param string $query Can be null as well, for caching
  952. * @param int $x Column num to return
  953. * @param int $y Row num to return
  954. * @return mixed Database query results
  955. */
  956. function get_var($query=null, $x = 0, $y = 0) {
  957. $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
  958. if ( $query )
  959. $this->query($query);
  960. // Extract var out of cached results based x,y vals
  961. if ( !empty( $this->last_result[$y] ) ) {
  962. $values = array_values(get_object_vars($this->last_result[$y]));
  963. }
  964. // If there is a value return it else return null
  965. return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
  966. }
  967. /**
  968. * Retrieve one row from the database.
  969. *
  970. * @since 0.71
  971. *
  972. * @param string $query SQL query
  973. * @param string $output ARRAY_A | ARRAY_N | OBJECT
  974. * @param int $y Row num to return
  975. * @return mixed Database query results
  976. */
  977. function get_row($query = null, $output = OBJECT, $y = 0) {
  978. $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
  979. if ( $query )
  980. $this->query($query);
  981. else
  982. return null;
  983. if ( !isset($this->last_result[$y]) )
  984. return null;
  985. if ( $output == OBJECT ) {
  986. return $this->last_result[$y] ? $this->last_result[$y] : null;
  987. } elseif ( $output == ARRAY_A ) {
  988. return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
  989. } elseif ( $output == ARRAY_N ) {
  990. return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
  991. } else {
  992. $this->print_error(/*WP_I18N_DB_GETROW_ERROR*/" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N"/*/WP_I18N_DB_GETROW_ERROR*/);
  993. }
  994. }
  995. /**
  996. * Retrieve one column from the database.
  997. *
  998. * @since 0.71
  999. *
  1000. * @param string $query Can be null as well, for caching
  1001. * @param int $x Col num to return. Starts from 0.
  1002. * @return array Column results
  1003. */
  1004. function get_col($query = null , $x = 0) {
  1005. if ( $query )
  1006. $this->query($query);
  1007. $new_array = array();
  1008. // Extract the column values
  1009. for ( $i=0; $i < count($this->last_result); $i++ ) {
  1010. $new_array[$i] = $this->get_var(null, $x, $i);
  1011. }
  1012. return $new_array;
  1013. }
  1014. /**
  1015. * Retrieve an entire result set from the database.
  1016. *
  1017. * @since 0.71
  1018. *
  1019. * @param string|null $query Can also be null to pull from the cache
  1020. * @param string $output ARRAY_A | ARRAY_N | OBJECT_K | OBJECT
  1021. * @return mixed Database query results
  1022. */
  1023. function get_results($query = null, $output = OBJECT) {
  1024. $this->func_call = "\$db->get_results(\"$query\", $output)";
  1025. if ( $query )
  1026. $this->query($query);
  1027. else
  1028. return null;
  1029. if ( $output == OBJECT ) {
  1030. // Return an integer-keyed array of row objects
  1031. return $this->last_result;
  1032. } elseif ( $output == OBJECT_K ) {
  1033. // Return an array of row objects with keys from column 1
  1034. // (Duplicates are discarded)
  1035. foreach ( $this->last_result as $row ) {
  1036. $key = array_shift( get_object_vars( $row ) );
  1037. if ( !isset( $new_array[ $key ] ) )
  1038. $new_array[ $key ] = $row;
  1039. }
  1040. return $new_array;
  1041. } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
  1042. // Return an integer-keyed array of...
  1043. if ( $this->last_result ) {
  1044. $i = 0;
  1045. foreach( (array) $this->last_result as $row ) {
  1046. if ( $output == ARRAY_N ) {
  1047. // ...integer-keyed row arrays
  1048. $new_array[$i] = array_values( get_object_vars( $row ) );
  1049. } else {
  1050. // ...column name-keyed row arrays
  1051. $new_array[$i] = get_object_vars( $row );
  1052. }
  1053. ++$i;
  1054. }
  1055. return $new_array;
  1056. }
  1057. }
  1058. }
  1059. /**
  1060. * Retrieve column metadata from the last query.
  1061. *
  1062. * @since 0.71
  1063. *
  1064. * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
  1065. * @param int $col_offset 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
  1066. * @return mixed Column Results
  1067. */
  1068. function get_col_info($info_type = 'name', $col_offset = -1) {
  1069. if ( $this->col_info ) {
  1070. if ( $col_offset == -1 ) {
  1071. $i = 0;
  1072. foreach( (array) $this->col_info as $col ) {
  1073. $new_array[$i] = $col->{$info_type};
  1074. $i++;
  1075. }
  1076. return $new_array;
  1077. } else {
  1078. return $this->col_info[$col_offset]->{$info_type};
  1079. }
  1080. }
  1081. }
  1082. /**
  1083. * Starts the timer, for debugging purposes.
  1084. *
  1085. * @since 1.5.0
  1086. *
  1087. * @return bool Always returns true
  1088. */
  1089. function timer_start() {
  1090. $mtime = microtime();
  1091. $mtime = explode(' ', $mtime);
  1092. $this->time_start = $mtime[1] + $mtime[0];
  1093. return true;
  1094. }
  1095. /**
  1096. * Stops the debugging timer.
  1097. *
  1098. * @since 1.5.0
  1099. *
  1100. * @return int Total time spent on the query, in milliseconds
  1101. */
  1102. function timer_stop() {
  1103. $mtime = microtime();
  1104. $mtime = explode(' ', $mtime);
  1105. $time_end = $mtime[1] + $mtime[0];
  1106. $time_total = $time_end - $this->time_start;
  1107. return $time_total;
  1108. }
  1109. /**
  1110. * Wraps fatal errors in a nice header and footer and dies.
  1111. *
  1112. * @since 1.5.0
  1113. *
  1114. * @param string $message
  1115. * @return unknown
  1116. */
  1117. function bail($message) {
  1118. if ( !$this->show_errors ) {
  1119. if ( class_exists('WP_Error') )
  1120. $this->error = new WP_Error('500', $message);
  1121. else
  1122. $this->error = $message;
  1123. return false;
  1124. }
  1125. wp_die($message);
  1126. }
  1127. /**
  1128. * Whether or not MySQL database is minimal required version.
  1129. *
  1130. * @since 2.5.0
  1131. * @uses $wp_version
  1132. *
  1133. * @return WP_Error
  1134. */
  1135. function check_database_version()
  1136. {
  1137. global $wp_version;
  1138. // Base on database type
  1139. //
  1140. if ($this->db_type == "mysql") {
  1141. // Make sure the server has MySQL 4.0
  1142. if ( version_compare($this->db_version(), '4.0.0', '<') )
  1143. return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version));
  1144. }
  1145. }
  1146. /**
  1147. * Whether of not the database version supports collation.
  1148. *
  1149. * Called when WordPress is generating the table scheme.
  1150. *
  1151. * @since 2.5.0
  1152. *
  1153. * @return bool True if collation is supported, false if version does not
  1154. */
  1155. function supports_collation()
  1156. {
  1157. return false;
  1158. }
  1159. /**
  1160. * Retrieve the name of the function that called wpdb.
  1161. *
  1162. * Requires PHP 4.3 and searches up the list of functions until it reaches
  1163. * the one that would most logically had called this method.
  1164. *
  1165. * @since 2.5.0
  1166. *
  1167. * @return string The name of the calling function
  1168. */
  1169. function get_caller() {
  1170. // requires PHP 4.3+
  1171. if ( !is_callable('debug_backtrace') )
  1172. return '';
  1173. $bt = debug_backtrace();
  1174. $caller = array();
  1175. $bt = array_reverse( $bt );
  1176. foreach ( (array) $bt as $call ) {
  1177. if ( @$call['class'] == __CLASS__ )
  1178. continue;
  1179. $function = $call['function'];
  1180. if ( isset( $call['class'] ) )
  1181. $function = $call['class'] . "->$function";
  1182. $caller[] = $function;
  1183. }
  1184. $caller = join( ', ', $caller );
  1185. return $caller;
  1186. }
  1187. /**
  1188. * The database version number
  1189. * @param false|string|resource $dbh_or_table (not implemented) Which database to test. False = the currently selected database, string = the database containing the specified table, resource = the database corresponding to the specified mysql resource.
  1190. * @return false|string false on failure, version number on success
  1191. */
  1192. function db_version() {
  1193. return '5.0';
  1194. }
  1195. }