Ticket #10918: 10918-2.patch
File 10918-2.patch, 251.8 KB (added by , 15 years ago) |
---|
-
wp-admin/setup-config.php
91 91 <li>Database username</li> 92 92 <li>Database password</li> 93 93 <li>Database host</li> 94 <li>Database type</li> 94 95 <li>Table prefix (if you want to run more than one WordPress in a single database) </li> 95 96 </ol> 96 97 <p><strong>If for any reason this automatic file creation doesn't work, don't worry. All this does is fill in the database information to a configuration file. You may also simply open <code>wp-config-sample.php</code> in a text editor, fill in your information, and save it as <code>wp-config.php</code>. </strong></p> … … 114 115 <tr> 115 116 <th scope="row"><label for="uname">User Name</label></th> 116 117 <td><input name="uname" id="uname" type="text" size="25" value="username" /></td> 117 <td>Your MySQLusername</td>118 <td>Your database username</td> 118 119 </tr> 119 120 <tr> 120 121 <th scope="row"><label for="pwd">Password</label></th> 121 122 <td><input name="pwd" id="pwd" type="text" size="25" value="password" /></td> 122 <td>...and MySQLpassword.</td>123 <td>...and database password.</td> 123 124 </tr> 124 125 <tr> 125 126 <th scope="row"><label for="dbhost">Database Host</label></th> 126 127 <td><input name="dbhost" id="dbhost" type="text" size="25" value="localhost" /></td> 127 <td>99% chance you won't need to change this value.</td> 128 <td>DB host, 99% chance you won't need to change this value.</td><?php 129 130 $folders = array(); 131 if ( is_dir(ABSPATH . 'wp-includes/wp-db/') ) { 132 $dir = ABSPATH . 'wp-includes/wp-db/'; 133 $handle = dir($dir); 134 while ( $filename = $handle->read() ) { 135 $restricted = array('.', '..', '.svn'); 136 $path = realpath($dir.$filename); 137 if ( is_dir($path) && !in_array($filename, $restricted) ) { 138 if ( $path !== '/' ) { 139 $path .= '/'; 140 } 141 if ( is_readable($path) ) { 142 $folders[] = $filename; 143 } 144 } 145 } 146 } 147 if ( empty($folders) ) { ?> 148 149 <input name="dbtype" id="dbtype" type="hidden" value="mysql" /><?php 150 } else { ?> 151 128 152 </tr> 129 153 <tr> 154 <th scope="row"><label for="dbtype">Database Type</label></th> 155 <td> 156 <select name="dbtype" id="dbtype"><?php 157 158 foreach ( $folders as $folder ) { 159 // mysql as default 160 if ( $folder == 'mysql' ) { 161 echo "<option value=\"$folder\">MySQL</option>\n"; 162 } elseif ( $folder == 'sqlsrv' ) { 163 echo "<option value=\"$folder\">SQL Server using MS PHP driver (SQLSRV; PHP5 & Win req.)</option>\n"; 164 } elseif ( $folder == 'mssql' ) { 165 echo "<option value=\"$folder\">SQL Server using PHP native driver (MSSQL)</option>\n"; 166 } else { 167 echo "<option value=\"$folder\">$folder</option>\n"; 168 } 169 } ?> 170 171 </select> 172 <td>The DB Type.</td><?php 173 } ?> 174 175 </tr> 176 <tr> 130 177 <th scope="row"><label for="prefix">Table Prefix</label></th> 131 178 <td><input name="prefix" id="prefix" type="text" id="prefix" value="wp_" size="25" /></td> 132 179 <td>If you want to run multiple WordPress installations in a single database, change this.</td> … … 142 189 $uname = trim($_POST['uname']); 143 190 $passwrd = trim($_POST['pwd']); 144 191 $dbhost = trim($_POST['dbhost']); 192 $dbtype = trim($_POST['dbtype']); 145 193 $prefix = trim($_POST['prefix']); 146 194 if (empty($prefix)) $prefix = 'wp_'; 147 195 … … 153 201 define('DB_USER', $uname); 154 202 define('DB_PASSWORD', $passwrd); 155 203 define('DB_HOST', $dbhost); 204 define('DB_TYPE', $dbtype); 156 205 /**#@-*/ 157 206 158 207 // We'll fail here if the values are no good. … … 174 223 case "define('DB_HOST'": 175 224 $configFile[$line_num] = str_replace("localhost", $dbhost, $line); 176 225 break; 226 case "define('DB_TYPE'": 227 $configFile[$line_num] = str_replace('mysql', $dbtype, $line); 228 break; 177 229 case '$table_prefix =': 178 230 $configFile[$line_num] = str_replace('wp_', $prefix, $line); 179 231 break; -
wp-config-sample.php
1 1 <?php 2 /** 2 /** 3 3 * The base configurations of the WordPress. 4 4 * 5 5 * This file has the following configurations: MySQL settings, Table Prefix, … … 18 18 /** The name of the database for WordPress */ 19 19 define('DB_NAME', 'putyourdbnamehere'); 20 20 21 /** MySQL database username */21 /** Database username */ 22 22 define('DB_USER', 'usernamehere'); 23 23 24 /** MySQL database password */24 /** Database password */ 25 25 define('DB_PASSWORD', 'yourpasswordhere'); 26 26 27 /** MySQLhostname */27 /** Database hostname */ 28 28 define('DB_HOST', 'localhost'); 29 29 30 /** Database Type. Defaults to mysql */ 31 define('DB_TYPE', 'mysql'); 32 30 33 /** Database Charset to use in creating database tables. */ 31 34 define('DB_CHARSET', 'utf8'); 32 35 -
wp-includes/wp-db.php
1 1 <?php 2 /** 3 * WordPress DB Class 4 * 5 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)} 6 * 7 * @package WordPress 8 * @subpackage Database 9 * @since 0.71 10 */ 2 // help maintain backwards compatibility. 3 if ( !defined('DB_TYPE') ) { 4 define('DB_TYPE', 'mysql'); 5 } 11 6 12 /** 13 * @since 0.71 14 */ 15 define('EZSQL_VERSION', 'WP1.25'); 7 require_once(dirname(__FILE__) . '/wp-db/' . DB_TYPE . '/' . DB_TYPE . '.php'); 16 8 17 /** 18 * @since 0.71 19 */ 20 define('OBJECT', 'OBJECT', true); 21 22 /** 23 * @since {@internal Version Unknown}} 24 */ 25 define('OBJECT_K', 'OBJECT_K', false); 26 27 /** 28 * @since 0.71 29 */ 30 define('ARRAY_A', 'ARRAY_A', false); 31 32 /** 33 * @since 0.71 34 */ 35 define('ARRAY_N', 'ARRAY_N', false); 36 37 /** 38 * WordPress Database Access Abstraction Object 39 * 40 * It is possible to replace this class with your own 41 * by setting the $wpdb global variable in wp-content/db.php 42 * file with your class. You can name it wpdb also, since 43 * this file will not be included, if the other file is 44 * available. 45 * 46 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class 47 * 48 * @package WordPress 49 * @subpackage Database 50 * @since 0.71 51 * @final 52 */ 53 class wpdb { 54 9 if ( !isset($wpdb) ) { 55 10 /** 56 * Whether to show SQL/DB errors 57 * 58 * @since 0.71 59 * @access private 60 * @var bool 61 */ 62 var $show_errors = false; 63 64 /** 65 * Whether to suppress errors during the DB bootstrapping. 66 * 67 * @access private 68 * @since {@internal Version Unknown}} 69 * @var bool 70 */ 71 var $suppress_errors = false; 72 73 /** 74 * The last error during query. 75 * 76 * @since {@internal Version Unknown}} 77 * @var string 78 */ 79 var $last_error = ''; 80 81 /** 82 * Amount of queries made 83 * 84 * @since 1.2.0 85 * @access private 86 * @var int 87 */ 88 var $num_queries = 0; 89 90 /** 91 * Saved result of the last query made 92 * 93 * @since 1.2.0 94 * @access private 95 * @var array 96 */ 97 var $last_query; 98 99 /** 100 * Saved info on the table column 101 * 102 * @since 1.2.0 103 * @access private 104 * @var array 105 */ 106 var $col_info; 107 108 /** 109 * Saved queries that were executed 110 * 111 * @since 1.5.0 112 * @access private 113 * @var array 114 */ 115 var $queries; 116 117 /** 118 * WordPress table prefix 119 * 120 * You can set this to have multiple WordPress installations 121 * in a single database. The second reason is for possible 122 * security precautions. 123 * 124 * @since 0.71 125 * @access private 126 * @var string 127 */ 128 var $prefix = ''; 129 130 /** 131 * Whether the database queries are ready to start executing. 132 * 133 * @since 2.5.0 134 * @access private 135 * @var bool 136 */ 137 var $ready = false; 138 139 /** 140 * WordPress Posts table 141 * 142 * @since 1.5.0 143 * @access public 144 * @var string 145 */ 146 var $posts; 147 148 /** 149 * WordPress Users table 150 * 151 * @since 1.5.0 152 * @access public 153 * @var string 154 */ 155 var $users; 156 157 /** 158 * WordPress Categories table 159 * 160 * @since 1.5.0 161 * @access public 162 * @var string 163 */ 164 var $categories; 165 166 /** 167 * WordPress Post to Category table 168 * 169 * @since 1.5.0 170 * @access public 171 * @var string 172 */ 173 var $post2cat; 174 175 /** 176 * WordPress Comments table 177 * 178 * @since 1.5.0 179 * @access public 180 * @var string 181 */ 182 var $comments; 183 184 /** 185 * WordPress Links table 186 * 187 * @since 1.5.0 188 * @access public 189 * @var string 190 */ 191 var $links; 192 193 /** 194 * WordPress Options table 195 * 196 * @since 1.5.0 197 * @access public 198 * @var string 199 */ 200 var $options; 201 202 /** 203 * WordPress Post Metadata table 204 * 205 * @since {@internal Version Unknown}} 206 * @access public 207 * @var string 208 */ 209 var $postmeta; 210 211 /** 212 * WordPress Comment Metadata table 213 * 214 * @since 2.9 215 * @access public 216 * @var string 217 */ 218 var $commentmeta; 219 220 /** 221 * WordPress User Metadata table 222 * 223 * @since 2.3.0 224 * @access public 225 * @var string 226 */ 227 var $usermeta; 228 229 /** 230 * WordPress Terms table 231 * 232 * @since 2.3.0 233 * @access public 234 * @var string 235 */ 236 var $terms; 237 238 /** 239 * WordPress Term Taxonomy table 240 * 241 * @since 2.3.0 242 * @access public 243 * @var string 244 */ 245 var $term_taxonomy; 246 247 /** 248 * WordPress Term Relationships table 249 * 250 * @since 2.3.0 251 * @access public 252 * @var string 253 */ 254 var $term_relationships; 255 256 /** 257 * List of WordPress tables 258 * 259 * @since {@internal Version Unknown}} 260 * @access private 261 * @var array 262 */ 263 var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options', 264 'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta'); 265 266 /** 267 * List of deprecated WordPress tables 268 * 269 * @since 2.9.0 270 * @access private 271 * @var array 272 */ 273 var $old_tables = array('categories', 'post2cat', 'link2cat'); 274 275 276 /** 277 * Format specifiers for DB columns. Columns not listed here default to %s. Initialized in wp-settings.php. 278 * 279 * Keys are colmn names, values are format types: 'ID' => '%d' 280 * 281 * @since 2.8.0 282 * @see wpdb:prepare() 283 * @see wpdb:insert() 284 * @see wpdb:update() 285 * @access public 286 * @war array 287 */ 288 var $field_types = array(); 289 290 /** 291 * Database table columns charset 292 * 293 * @since 2.2.0 294 * @access public 295 * @var string 296 */ 297 var $charset; 298 299 /** 300 * Database table columns collate 301 * 302 * @since 2.2.0 303 * @access public 304 * @var string 305 */ 306 var $collate; 307 308 /** 309 * Whether to use mysql_real_escape_string 310 * 311 * @since 2.8.0 312 * @access public 313 * @var bool 314 */ 315 var $real_escape = false; 316 317 /** 318 * Database Username 319 * 320 * @since 2.9.0 321 * @access private 322 * @var string 323 */ 324 var $dbuser; 325 326 /** 327 * Connects to the database server and selects a database 328 * 329 * PHP4 compatibility layer for calling the PHP5 constructor. 330 * 331 * @uses wpdb::__construct() Passes parameters and returns result 332 * @since 0.71 333 * 334 * @param string $dbuser MySQL database user 335 * @param string $dbpassword MySQL database password 336 * @param string $dbname MySQL database name 337 * @param string $dbhost MySQL database host 338 */ 339 function wpdb($dbuser, $dbpassword, $dbname, $dbhost) { 340 return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); 341 } 342 343 /** 344 * Connects to the database server and selects a database 345 * 346 * PHP5 style constructor for compatibility with PHP5. Does 347 * the actual setting up of the class properties and connection 348 * to the database. 349 * 350 * @since 2.0.8 351 * 352 * @param string $dbuser MySQL database user 353 * @param string $dbpassword MySQL database password 354 * @param string $dbname MySQL database name 355 * @param string $dbhost MySQL database host 356 */ 357 function __construct($dbuser, $dbpassword, $dbname, $dbhost) { 358 register_shutdown_function(array(&$this, "__destruct")); 359 360 if ( defined('WP_DEBUG') and WP_DEBUG == true ) 361 $this->show_errors(); 362 363 if ( defined('DB_CHARSET') ) 364 $this->charset = DB_CHARSET; 365 366 if ( defined('DB_COLLATE') ) 367 $this->collate = DB_COLLATE; 368 369 $this->dbuser = $dbuser; 370 371 $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true); 372 if (!$this->dbh) { 373 $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/" 374 <h1>Error establishing a database connection</h1> 375 <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> 376 <ul> 377 <li>Are you sure you have the correct username and password?</li> 378 <li>Are you sure that you have typed the correct hostname?</li> 379 <li>Are you sure that the database server is running?</li> 380 </ul> 381 <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> 382 "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail'); 383 return; 384 } 385 386 $this->ready = true; 387 388 if ( $this->has_cap( 'collation' ) ) { 389 if ( !empty($this->charset) ) { 390 if ( function_exists('mysql_set_charset') ) { 391 mysql_set_charset($this->charset, $this->dbh); 392 $this->real_escape = true; 393 } else { 394 $collation_query = "SET NAMES '{$this->charset}'"; 395 if ( !empty($this->collate) ) 396 $collation_query .= " COLLATE '{$this->collate}'"; 397 $this->query($collation_query); 398 } 399 } 400 } 401 402 $this->select($dbname); 403 } 404 405 /** 406 * PHP5 style destructor and will run when database object is destroyed. 407 * 408 * @since 2.0.8 409 * 410 * @return bool Always true 411 */ 412 function __destruct() { 413 return true; 414 } 415 416 /** 417 * Sets the table prefix for the WordPress tables. 418 * 419 * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to 420 * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix. 421 * 422 * @since 2.5.0 423 * 424 * @param string $prefix Alphanumeric name for the new prefix. 425 * @return string|WP_Error Old prefix or WP_Error on error 426 */ 427 function set_prefix($prefix) { 428 429 if ( preg_match('|[^a-z0-9_]|i', $prefix) ) 430 return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/); 431 432 $old_prefix = $this->prefix; 433 $this->prefix = $prefix; 434 435 foreach ( (array) $this->tables as $table ) 436 $this->$table = $this->prefix . $table; 437 438 if ( defined('CUSTOM_USER_TABLE') ) 439 $this->users = CUSTOM_USER_TABLE; 440 441 if ( defined('CUSTOM_USER_META_TABLE') ) 442 $this->usermeta = CUSTOM_USER_META_TABLE; 443 444 return $old_prefix; 445 } 446 447 /** 448 * Selects a database using the current database connection. 449 * 450 * The database name will be changed based on the current database 451 * connection. On failure, the execution will bail and display an DB error. 452 * 453 * @since 0.71 454 * 455 * @param string $db MySQL database name 456 * @return null Always null. 457 */ 458 function select($db) { 459 if (!@mysql_select_db($db, $this->dbh)) { 460 $this->ready = false; 461 $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/' 462 <h1>Can’t select database</h1> 463 <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> 464 <ul> 465 <li>Are you sure it exists?</li> 466 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> 467 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li> 468 </ul> 469 <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, $this->dbuser), 'db_select_fail'); 470 return; 471 } 472 } 473 474 function _weak_escape($string) { 475 return addslashes($string); 476 } 477 478 function _real_escape($string) { 479 if ( $this->dbh && $this->real_escape ) 480 return mysql_real_escape_string( $string, $this->dbh ); 481 else 482 return addslashes( $string ); 483 } 484 485 function _escape($data) { 486 if ( is_array($data) ) { 487 foreach ( (array) $data as $k => $v ) { 488 if ( is_array($v) ) 489 $data[$k] = $this->_escape( $v ); 490 else 491 $data[$k] = $this->_real_escape( $v ); 492 } 493 } else { 494 $data = $this->_real_escape( $data ); 495 } 496 497 return $data; 498 } 499 500 /** 501 * Escapes content for insertion into the database using addslashes(), for security 502 * 503 * @since 0.71 504 * 505 * @param string|array $data 506 * @return string query safe string 507 */ 508 function escape($data) { 509 if ( is_array($data) ) { 510 foreach ( (array) $data as $k => $v ) { 511 if ( is_array($v) ) 512 $data[$k] = $this->escape( $v ); 513 else 514 $data[$k] = $this->_weak_escape( $v ); 515 } 516 } else { 517 $data = $this->_weak_escape( $data ); 518 } 519 520 return $data; 521 } 522 523 /** 524 * Escapes content by reference for insertion into the database, for security 525 * 526 * @since 2.3.0 527 * 528 * @param string $s 529 */ 530 function escape_by_ref(&$string) { 531 $string = $this->_real_escape( $string ); 532 } 533 534 /** 535 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. 536 * 537 * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string). 538 * Does not support sign, padding, alignment, width or precision specifiers. 539 * Does not support argument numbering/swapping. 540 * 541 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. 542 * 543 * Both %d and %s should be left unquoted in the query string. 544 * 545 * <code> 546 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 ) 547 * </code> 548 * 549 * @link http://php.net/sprintf Description of syntax. 550 * @since 2.3.0 551 * 552 * @param string $query Query statement with sprintf()-like placeholders 553 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 554 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 555 * @return null|string Sanitized query string 556 */ 557 function prepare($query = null) { // ( $query, *$args ) 558 if ( is_null( $query ) ) 559 return; 560 $args = func_get_args(); 561 array_shift($args); 562 // If args were passed as an array (as in vsprintf), move them up 563 if ( isset($args[0]) && is_array($args[0]) ) 564 $args = $args[0]; 565 $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it 566 $query = str_replace('"%s"', '%s', $query); // doublequote unquoting 567 $query = str_replace('%s', "'%s'", $query); // quote the strings 568 array_walk($args, array(&$this, 'escape_by_ref')); 569 return @vsprintf($query, $args); 570 } 571 572 /** 573 * Print SQL/DB error. 574 * 575 * @since 0.71 576 * @global array $EZSQL_ERROR Stores error information of query and error string 577 * 578 * @param string $str The error to display 579 * @return bool False if the showing of errors is disabled. 580 */ 581 function print_error($str = '') { 582 global $EZSQL_ERROR; 583 584 if (!$str) $str = mysql_error($this->dbh); 585 $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str); 586 587 if ( $this->suppress_errors ) 588 return false; 589 590 if ( $caller = $this->get_caller() ) 591 $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); 592 else 593 $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); 594 595 $log_error = true; 596 if ( ! function_exists('error_log') ) 597 $log_error = false; 598 599 $log_file = @ini_get('error_log'); 600 if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) ) 601 $log_error = false; 602 603 if ( $log_error ) 604 @error_log($error_str, 0); 605 606 // Is error output turned on or not.. 607 if ( !$this->show_errors ) 608 return false; 609 610 $str = htmlspecialchars($str, ENT_QUOTES); 611 $query = htmlspecialchars($this->last_query, ENT_QUOTES); 612 613 // If there is an error then take note of it 614 print "<div id='error'> 615 <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br /> 616 <code>$query</code></p> 617 </div>"; 618 } 619 620 /** 621 * Enables showing of database errors. 622 * 623 * This function should be used only to enable showing of errors. 624 * wpdb::hide_errors() should be used instead for hiding of errors. However, 625 * this function can be used to enable and disable showing of database 626 * errors. 627 * 628 * @since 0.71 629 * 630 * @param bool $show Whether to show or hide errors 631 * @return bool Old value for showing errors. 632 */ 633 function show_errors( $show = true ) { 634 $errors = $this->show_errors; 635 $this->show_errors = $show; 636 return $errors; 637 } 638 639 /** 640 * Disables showing of database errors. 641 * 642 * @since 0.71 643 * 644 * @return bool Whether showing of errors was active or not 645 */ 646 function hide_errors() { 647 $show = $this->show_errors; 648 $this->show_errors = false; 649 return $show; 650 } 651 652 /** 653 * Whether to suppress database errors. 654 * 655 * @param unknown_type $suppress 656 * @return unknown 657 */ 658 function suppress_errors( $suppress = true ) { 659 $errors = $this->suppress_errors; 660 $this->suppress_errors = $suppress; 661 return $errors; 662 } 663 664 /** 665 * Kill cached query results. 666 * 667 * @since 0.71 668 */ 669 function flush() { 670 $this->last_result = array(); 671 $this->col_info = null; 672 $this->last_query = null; 673 } 674 675 /** 676 * Perform a MySQL database query, using current database connection. 677 * 678 * More information can be found on the codex page. 679 * 680 * @since 0.71 681 * 682 * @param string $query 683 * @return int|false Number of rows affected/selected or false on error 684 */ 685 function query($query) { 686 if ( ! $this->ready ) 687 return false; 688 689 // filter the query, if filters are available 690 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method 691 if ( function_exists('apply_filters') ) 692 $query = apply_filters('query', $query); 693 694 // initialise return 695 $return_val = 0; 696 $this->flush(); 697 698 // Log how the function was called 699 $this->func_call = "\$db->query(\"$query\")"; 700 701 // Keep track of the last query for debug.. 702 $this->last_query = $query; 703 704 // Perform the query via std mysql_query function.. 705 if ( defined('SAVEQUERIES') && SAVEQUERIES ) 706 $this->timer_start(); 707 708 $this->result = @mysql_query($query, $this->dbh); 709 ++$this->num_queries; 710 711 if ( defined('SAVEQUERIES') && SAVEQUERIES ) 712 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); 713 714 // If there is an error then take note of it.. 715 if ( $this->last_error = mysql_error($this->dbh) ) { 716 $this->print_error(); 717 return false; 718 } 719 720 if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) { 721 $this->rows_affected = mysql_affected_rows($this->dbh); 722 // Take note of the insert_id 723 if ( preg_match("/^\\s*(insert|replace) /i",$query) ) { 724 $this->insert_id = mysql_insert_id($this->dbh); 725 } 726 // Return number of rows affected 727 $return_val = $this->rows_affected; 728 } else { 729 $i = 0; 730 while ($i < @mysql_num_fields($this->result)) { 731 $this->col_info[$i] = @mysql_fetch_field($this->result); 732 $i++; 733 } 734 $num_rows = 0; 735 while ( $row = @mysql_fetch_object($this->result) ) { 736 $this->last_result[$num_rows] = $row; 737 $num_rows++; 738 } 739 740 @mysql_free_result($this->result); 741 742 // Log number of rows the query returned 743 $this->num_rows = $num_rows; 744 745 // Return number of rows selected 746 $return_val = $this->num_rows; 747 } 748 749 return $return_val; 750 } 751 752 /** 753 * Insert a row into a table. 754 * 755 * <code> 756 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) 757 * </code> 758 * 759 * @since 2.5.0 760 * @see wpdb::prepare() 761 * 762 * @param string $table table name 763 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 764 * @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. 765 * @return int|false The number of rows inserted, or false on error. 766 */ 767 function insert($table, $data, $format = null) { 768 $formats = $format = (array) $format; 769 $fields = array_keys($data); 770 $formatted_fields = array(); 771 foreach ( $fields as $field ) { 772 if ( !empty($format) ) 773 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 774 elseif ( isset($this->field_types[$field]) ) 775 $form = $this->field_types[$field]; 776 else 777 $form = '%s'; 778 $formatted_fields[] = $form; 779 } 780 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')"; 781 return $this->query( $this->prepare( $sql, $data) ); 782 } 783 784 785 /** 786 * Update a row in the table 787 * 788 * <code> 789 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) 790 * </code> 791 * 792 * @since 2.5.0 793 * @see wpdb::prepare() 794 * 795 * @param string $table table name 796 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 797 * @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". 798 * @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. 799 * @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. 800 * @return int|false The number of rows updated, or false on error. 801 */ 802 function update($table, $data, $where, $format = null, $where_format = null) { 803 if ( !is_array( $where ) ) 804 return false; 805 806 $formats = $format = (array) $format; 807 $bits = $wheres = array(); 808 foreach ( (array) array_keys($data) as $field ) { 809 if ( !empty($format) ) 810 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 811 elseif ( isset($this->field_types[$field]) ) 812 $form = $this->field_types[$field]; 813 else 814 $form = '%s'; 815 $bits[] = "`$field` = {$form}"; 816 } 817 818 $where_formats = $where_format = (array) $where_format; 819 foreach ( (array) array_keys($where) as $field ) { 820 if ( !empty($where_format) ) 821 $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0]; 822 elseif ( isset($this->field_types[$field]) ) 823 $form = $this->field_types[$field]; 824 else 825 $form = '%s'; 826 $wheres[] = "`$field` = {$form}"; 827 } 828 829 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ); 830 return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) ); 831 } 832 833 /** 834 * Retrieve one variable from the database. 835 * 836 * Executes a SQL query and returns the value from the SQL result. 837 * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified. 838 * If $query is null, this function returns the value in the specified column and row from the previous SQL result. 839 * 840 * @since 0.71 841 * 842 * @param string|null $query SQL query. If null, use the result from the previous query. 843 * @param int $x (optional) Column of value to return. Indexed from 0. 844 * @param int $y (optional) Row of value to return. Indexed from 0. 845 * @return string Database query result 846 */ 847 function get_var($query=null, $x = 0, $y = 0) { 848 $this->func_call = "\$db->get_var(\"$query\",$x,$y)"; 849 if ( $query ) 850 $this->query($query); 851 852 // Extract var out of cached results based x,y vals 853 if ( !empty( $this->last_result[$y] ) ) { 854 $values = array_values(get_object_vars($this->last_result[$y])); 855 } 856 857 // If there is a value return it else return null 858 return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null; 859 } 860 861 /** 862 * Retrieve one row from the database. 863 * 864 * Executes a SQL query and returns the row from the SQL result. 865 * 866 * @since 0.71 867 * 868 * @param string|null $query SQL query. 869 * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively. 870 * @param int $y (optional) Row to return. Indexed from 0. 871 * @return mixed Database query result in format specifed by $output 872 */ 873 function get_row($query = null, $output = OBJECT, $y = 0) { 874 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; 875 if ( $query ) 876 $this->query($query); 877 else 878 return null; 879 880 if ( !isset($this->last_result[$y]) ) 881 return null; 882 883 if ( $output == OBJECT ) { 884 return $this->last_result[$y] ? $this->last_result[$y] : null; 885 } elseif ( $output == ARRAY_A ) { 886 return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null; 887 } elseif ( $output == ARRAY_N ) { 888 return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null; 889 } else { 890 $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*/); 891 } 892 } 893 894 /** 895 * Retrieve one column from the database. 896 * 897 * Executes a SQL query and returns the column from the SQL result. 898 * If the SQL result contains more than one column, this function returns the column specified. 899 * If $query is null, this function returns the specified column from the previous SQL result. 900 * 901 * @since 0.71 902 * 903 * @param string|null $query SQL query. If null, use the result from the previous query. 904 * @param int $x Column to return. Indexed from 0. 905 * @return array Database query result. Array indexed from 0 by SQL result row number. 906 */ 907 function get_col($query = null , $x = 0) { 908 if ( $query ) 909 $this->query($query); 910 911 $new_array = array(); 912 // Extract the column values 913 for ( $i=0; $i < count($this->last_result); $i++ ) { 914 $new_array[$i] = $this->get_var(null, $x, $i); 915 } 916 return $new_array; 917 } 918 919 /** 920 * Retrieve an entire SQL result set from the database (i.e., many rows) 921 * 922 * Executes a SQL query and returns the entire SQL result. 923 * 924 * @since 0.71 925 * 926 * @param string $query SQL query. 927 * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded. 928 * @return mixed Database query results 929 */ 930 function get_results($query = null, $output = OBJECT) { 931 $this->func_call = "\$db->get_results(\"$query\", $output)"; 932 933 if ( $query ) 934 $this->query($query); 935 else 936 return null; 937 938 if ( $output == OBJECT ) { 939 // Return an integer-keyed array of row objects 940 return $this->last_result; 941 } elseif ( $output == OBJECT_K ) { 942 // Return an array of row objects with keys from column 1 943 // (Duplicates are discarded) 944 foreach ( $this->last_result as $row ) { 945 $key = array_shift( get_object_vars( $row ) ); 946 if ( !isset( $new_array[ $key ] ) ) 947 $new_array[ $key ] = $row; 948 } 949 return $new_array; 950 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { 951 // Return an integer-keyed array of... 952 if ( $this->last_result ) { 953 $i = 0; 954 foreach( (array) $this->last_result as $row ) { 955 if ( $output == ARRAY_N ) { 956 // ...integer-keyed row arrays 957 $new_array[$i] = array_values( get_object_vars( $row ) ); 958 } else { 959 // ...column name-keyed row arrays 960 $new_array[$i] = get_object_vars( $row ); 961 } 962 ++$i; 963 } 964 return $new_array; 965 } 966 } 967 } 968 969 /** 970 * Retrieve column metadata from the last query. 971 * 972 * @since 0.71 973 * 974 * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill 975 * @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 976 * @return mixed Column Results 977 */ 978 function get_col_info($info_type = 'name', $col_offset = -1) { 979 if ( $this->col_info ) { 980 if ( $col_offset == -1 ) { 981 $i = 0; 982 foreach( (array) $this->col_info as $col ) { 983 $new_array[$i] = $col->{$info_type}; 984 $i++; 985 } 986 return $new_array; 987 } else { 988 return $this->col_info[$col_offset]->{$info_type}; 989 } 990 } 991 } 992 993 /** 994 * Starts the timer, for debugging purposes. 995 * 996 * @since 1.5.0 997 * 998 * @return true 999 */ 1000 function timer_start() { 1001 $mtime = microtime(); 1002 $mtime = explode(' ', $mtime); 1003 $this->time_start = $mtime[1] + $mtime[0]; 1004 return true; 1005 } 1006 1007 /** 1008 * Stops the debugging timer. 1009 * 1010 * @since 1.5.0 1011 * 1012 * @return int Total time spent on the query, in milliseconds 1013 */ 1014 function timer_stop() { 1015 $mtime = microtime(); 1016 $mtime = explode(' ', $mtime); 1017 $time_end = $mtime[1] + $mtime[0]; 1018 $time_total = $time_end - $this->time_start; 1019 return $time_total; 1020 } 1021 1022 /** 1023 * Wraps errors in a nice header and footer and dies. 1024 * 1025 * Will not die if wpdb::$show_errors is true 1026 * 1027 * @since 1.5.0 1028 * 1029 * @param string $message The Error message 1030 * @param string $error_code (optional) A Computer readable string to identify the error. 1031 * @return false|void 1032 */ 1033 function bail($message, $error_code = '500') { 1034 if ( !$this->show_errors ) { 1035 if ( class_exists('WP_Error') ) 1036 $this->error = new WP_Error($error_code, $message); 1037 else 1038 $this->error = $message; 1039 return false; 1040 } 1041 wp_die($message); 1042 } 1043 1044 /** 1045 * Whether or not MySQL database is at least the required minimum version. 1046 * 1047 * @since 2.5.0 1048 * @uses $wp_version 1049 * 1050 * @return WP_Error 1051 */ 1052 function check_database_version() 1053 { 1054 global $wp_version; 1055 // Make sure the server has MySQL 4.0 1056 if ( version_compare($this->db_version(), '4.0.0', '<') ) 1057 return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version)); 1058 } 1059 1060 /** 1061 * Whether of not the database supports collation. 1062 * 1063 * Called when WordPress is generating the table scheme. 1064 * 1065 * @since 2.5.0 1066 * 1067 * @return bool True if collation is supported, false if version does not 1068 */ 1069 function supports_collation() { 1070 return $this->has_cap( 'collation' ); 1071 } 1072 1073 /** 1074 * Generic function to determine if a database supports a particular feature 1075 * @param string $db_cap the feature 1076 * @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. 1077 * @return bool 1078 */ 1079 function has_cap( $db_cap ) { 1080 $version = $this->db_version(); 1081 1082 switch ( strtolower( $db_cap ) ) : 1083 case 'collation' : // @since 2.5.0 1084 case 'group_concat' : // @since 2.7 1085 case 'subqueries' : // @since 2.7 1086 return version_compare($version, '4.1', '>='); 1087 break; 1088 endswitch; 1089 1090 return false; 1091 } 1092 1093 /** 1094 * Retrieve the name of the function that called wpdb. 1095 * 1096 * Requires PHP 4.3 and searches up the list of functions until it reaches 1097 * the one that would most logically had called this method. 1098 * 1099 * @since 2.5.0 1100 * 1101 * @return string The name of the calling function 1102 */ 1103 function get_caller() { 1104 // requires PHP 4.3+ 1105 if ( !is_callable('debug_backtrace') ) 1106 return ''; 1107 1108 $bt = debug_backtrace(); 1109 $caller = array(); 1110 1111 $bt = array_reverse( $bt ); 1112 foreach ( (array) $bt as $call ) { 1113 if ( @$call['class'] == __CLASS__ ) 1114 continue; 1115 $function = $call['function']; 1116 if ( isset( $call['class'] ) ) 1117 $function = $call['class'] . "->$function"; 1118 $caller[] = $function; 1119 } 1120 $caller = join( ', ', $caller ); 1121 1122 return $caller; 1123 } 1124 1125 /** 1126 * The database version number 1127 * @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. 1128 * @return false|string false on failure, version number on success 1129 */ 1130 function db_version() { 1131 return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh )); 1132 } 1133 } 1134 1135 if ( ! isset($wpdb) ) { 1136 /** 1137 * WordPress Database Object, if it isn't set already in wp-content/db.php 1138 * @global object $wpdb Creates a new wpdb object based on wp-config.php Constants for the database 1139 * @since 0.71 1140 */ 11 * WordPress Database Object, if it isn't set already in wp-content/db.php 12 * @global object $wpdb Creates a new wpdb object based on wp-config.php Constants for the database 13 * @since 0.71 14 */ 1141 15 $wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST); 1142 16 } 1143 ?> -
wp-includes/wp-db/mssql/mssql.php
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 MSSQL by A.Garcia and A.Gentile 8 * 9 * @package WordPress 10 * @subpackage Database 11 * @since 0.71 12 */ 13 14 /** 15 * @since 0.71 16 */ 17 define('EZSQL_VERSION', 'WP1.25'); 18 19 /** 20 * @since 0.71 21 */ 22 define('OBJECT', 'OBJECT', true); 23 24 /** 25 * @since {@internal Version Unknown}} 26 */ 27 define('OBJECT_K', 'OBJECT_K', false); 28 29 /** 30 * @since 0.71 31 */ 32 define('ARRAY_A', 'ARRAY_A', false); 33 34 /** 35 * @since 0.71 36 */ 37 define('ARRAY_N', 'ARRAY_N', false); 38 39 require_once 'translations/translations.php'; 40 41 /** 42 * WordPress Database Access Abstraction Object 43 * 44 * It is possible to replace this class with your own 45 * by setting the $wpdb global variable in wp-content/db.php 46 * file with your class. You can name it wpdb also, since 47 * this file will not be included, if the other file is 48 * available. 49 * 50 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class 51 * 52 * @package WordPress 53 * @subpackage Database 54 * @since 0.71 55 * @final 56 */ 57 class wpdb extends SQL_Translations { 58 59 /** 60 * Whether to show SQL/DB errors 61 * 62 * @since 0.71 63 * @access private 64 * @var bool 65 */ 66 var $show_errors = true; 67 68 /** 69 * Whether to suppress errors during the DB bootstrapping. 70 * 71 * @access private 72 * @since {@internal Version Unknown}} 73 * @var bool 74 */ 75 var $suppress_errors = false; 76 77 /** 78 * The last error during query. 79 * 80 * @since {@internal Version Unknown}} 81 * @var string 82 */ 83 var $last_error = ''; 84 85 /** 86 * Amount of queries made 87 * 88 * @since 1.2.0 89 * @access private 90 * @var int 91 */ 92 var $num_queries = 0; 93 94 /** 95 * Saved result of the last query made 96 * 97 * @since 1.2.0 98 * @access private 99 * @var array 100 */ 101 var $last_query; 102 103 /** 104 * Saved result of the last translated query made 105 * 106 * @since 1.2.0 107 * @access private 108 * @var array 109 */ 110 var $previous_query; 111 112 /** 113 * Saved info on the table column 114 * 115 * @since 1.2.0 116 * @access private 117 * @var array 118 */ 119 var $col_info; 120 121 /** 122 * Saved queries that were executed 123 * 124 * @since 1.5.0 125 * @access private 126 * @var array 127 */ 128 var $queries; 129 130 /** 131 * WordPress table prefix 132 * 133 * You can set this to have multiple WordPress installations 134 * in a single database. The second reason is for possible 135 * security precautions. 136 * 137 * @since 0.71 138 * @access private 139 * @var string 140 */ 141 var $prefix = ''; 142 143 /** 144 * Whether the database queries are ready to start executing. 145 * 146 * @since 2.5.0 147 * @access private 148 * @var bool 149 */ 150 var $ready = false; 151 152 /** 153 * WordPress Posts table 154 * 155 * @since 1.5.0 156 * @access public 157 * @var string 158 */ 159 var $posts; 160 161 /** 162 * WordPress Users table 163 * 164 * @since 1.5.0 165 * @access public 166 * @var string 167 */ 168 var $users; 169 170 /** 171 * WordPress Categories table 172 * 173 * @since 1.5.0 174 * @access public 175 * @var string 176 */ 177 var $categories; 178 179 /** 180 * WordPress Post to Category table 181 * 182 * @since 1.5.0 183 * @access public 184 * @var string 185 */ 186 var $post2cat; 187 188 /** 189 * WordPress Comments table 190 * 191 * @since 1.5.0 192 * @access public 193 * @var string 194 */ 195 var $comments; 196 197 /** 198 * WordPress Links table 199 * 200 * @since 1.5.0 201 * @access public 202 * @var string 203 */ 204 var $links; 205 206 /** 207 * WordPress Options table 208 * 209 * @since 1.5.0 210 * @access public 211 * @var string 212 */ 213 var $options; 214 215 /** 216 * WordPress Post Metadata table 217 * 218 * @since {@internal Version Unknown}} 219 * @access public 220 * @var string 221 */ 222 var $postmeta; 223 224 /** 225 * WordPress User Metadata table 226 * 227 * @since 2.3.0 228 * @access public 229 * @var string 230 */ 231 var $usermeta; 232 233 /** 234 * WordPress Terms table 235 * 236 * @since 2.3.0 237 * @access public 238 * @var string 239 */ 240 var $terms; 241 242 /** 243 * WordPress Term Taxonomy table 244 * 245 * @since 2.3.0 246 * @access public 247 * @var string 248 */ 249 var $term_taxonomy; 250 251 /** 252 * WordPress Term Relationships table 253 * 254 * @since 2.3.0 255 * @access public 256 * @var string 257 */ 258 var $term_relationships; 259 260 /** 261 * List of WordPress tables 262 * 263 * @since {@internal Version Unknown}} 264 * @access private 265 * @var array 266 */ 267 var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options', 268 'postmeta', 'terms', 'term_taxonomy', 'term_relationships'); 269 270 /** 271 * Format specifiers for DB columns. Columns not listed here default to %s. Initialized in wp-settings.php. 272 * 273 * Keys are colmn names, values are format types: 'ID' => '%d' 274 * 275 * @since 2.8.0 276 * @see wpdb:prepare() 277 * @see wpdb:insert() 278 * @see wpdb:update() 279 * @access public 280 * @war array 281 */ 282 var $field_types = array(); 283 284 /** 285 * Database table columns charset 286 * 287 * @since 2.2.0 288 * @access public 289 * @var string 290 */ 291 var $charset; 292 293 /** 294 * Database table columns collate 295 * 296 * @since 2.2.0 297 * @access public 298 * @var string 299 */ 300 var $collate; 301 302 /** 303 * Whether to use mysql_real_escape_string 304 * 305 * @since 2.8.0 306 * @access public 307 * @var bool 308 */ 309 var $real_escape = false; 310 311 /** 312 * Database type 313 * @access public 314 * @var string 315 */ 316 var $db_type; 317 318 /** 319 * Connects to the database server and selects a database 320 * 321 * PHP4 compatibility layer for calling the PHP5 constructor. 322 * 323 * @uses wpdb::__construct() Passes parameters and returns result 324 * @since 0.71 325 * 326 * @param string $dbtype database type 327 * @param string $dbuser database user 328 * @param string $dbpassword database password 329 * @param string $dbname database name 330 * @param string $dbhost database host 331 */ 332 function wpdb($dbuser, $dbpassword, $dbname, $dbhost) { 333 return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); 334 } 335 336 /** 337 * Connects to the database server and selects a database 338 * 339 * PHP5 style constructor for compatibility with PHP5. Does 340 * the actual setting up of the class properties and connection 341 * to the database. 342 * 343 * @since 2.0.8 344 * 345 * @param string $dbtype database type 346 * @param string $dbuser database user 347 * @param string $dbpassword database password 348 * @param string $dbname database name 349 * @param string $dbhost database host 350 */ 351 function __construct($dbuser, $dbpassword, $dbname, $dbhost) { 352 register_shutdown_function(array(&$this, "__destruct")); 353 354 if ( defined('WP_DEBUG') and WP_DEBUG == true ) { 355 $this->show_errors(); 356 } 357 358 if ( defined('DB_CHARSET') ) { 359 $this->charset = DB_CHARSET; 360 } 361 362 if ( defined('DB_COLLATE') ) { 363 $this->collate = DB_COLLATE; 364 } 365 parent::__construct(); 366 367 $this->db_type = DB_TYPE; 368 369 // Make sure the version is the same for your ntwdblib.dll. 370 // The TDS library and the ntwdblib.dll can't be speaking two different protocols. 371 putenv("TDSVER=70"); 372 373 // Set text limit sizes to max BEFORE connection is made 374 ini_set('mssql.textlimit', 2147483647); 375 ini_set('mssql.textsize', 2147483647); 376 377 if (get_magic_quotes_gpc()) { 378 $dbhost = trim(str_replace("\\\\", "\\", $dbhost)); 379 } 380 381 $this->dbh = mssql_connect($dbhost, $dbuser, $dbpassword); 382 mssql_min_error_severity(0); 383 mssql_min_message_severity(17); 384 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 399 $this->ready = true; 400 401 // Make sure textsize fields are set to max. 402 @mssql_query('SET TEXTSIZE 2147483647'); 403 /* SET NAMES doesn't translate 404 if ( $this->supports_collation() ) { 405 $collation_query = ''; 406 if ( !empty($this->charset) ) { 407 $collation_query = "SET NAMES '{$this->charset}'"; 408 if (!empty($this->collate) ) 409 $collation_query .= " COLLATE '{$this->collate}'"; 410 } 411 412 if ( !empty($collation_query) ) 413 $this->query($collation_query); 414 415 } 416 */ 417 $this->select($dbname); 418 } 419 420 /** 421 * PHP5 style destructor and will run when database object is destroyed. 422 * 423 * @since 2.0.8 424 * 425 * @return bool Always true 426 */ 427 function __destruct() { 428 return true; 429 } 430 431 /** 432 * Sets the table prefix for the WordPress tables. 433 * 434 * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to 435 * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix. 436 * 437 * @since 2.5.0 438 * 439 * @param string $prefix Alphanumeric name for the new prefix. 440 * @return string|WP_Error Old prefix or WP_Error on error 441 */ 442 function set_prefix($prefix) { 443 444 if ( preg_match('|[^a-z0-9_]|i', $prefix) ) { 445 return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/); 446 } 447 448 $old_prefix = $this->prefix; 449 $this->prefix = $prefix; 450 451 foreach ( (array) $this->tables as $table ) { 452 $this->$table = $this->prefix . $table; 453 } 454 455 if ( defined('CUSTOM_USER_TABLE') ) { 456 $this->users = CUSTOM_USER_TABLE; 457 } 458 459 if ( defined('CUSTOM_USER_META_TABLE') ) { 460 $this->usermeta = CUSTOM_USER_META_TABLE; 461 } 462 463 return $old_prefix; 464 } 465 466 /** 467 * Selects a database using the current database connection. 468 * 469 * The database name will be changed based on the current database 470 * connection. On failure, the execution will bail and display an DB error. 471 * 472 * @since 0.71 473 * 474 * @param string $db database name 475 * @return null Always null. 476 */ 477 function select($db) { 478 $result = false; 479 $result = mssql_select_db($db, $this->dbh); 480 481 if (!$result) { 482 $this->ready = false; 483 $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/' 484 <h1>Can’t select database</h1> 485 <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> 486 <ul> 487 <li>Are you sure it exists?</li> 488 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> 489 <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> 490 </ul> 491 <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)); 492 return; 493 } 494 } 495 496 /** 497 * Escapes content for insertion into the database, for security 498 * 499 * @since 0.71 500 * 501 * @param string $string 502 * @return string query safe string 503 */ 504 function escape($string) { 505 return str_replace("'", "''", $string); 506 } 507 508 /** 509 * Escapes content by reference for insertion into the database, for security 510 * 511 * @since 2.3.0 512 * 513 * @param string $s 514 */ 515 function escape_by_ref(&$s) { 516 $s = $this->escape($s); 517 } 518 519 /** 520 * Prepares a SQL query for safe use, using sprintf() syntax. 521 * 522 * @link http://php.net/sprintf See for syntax to use for query string. 523 * @since 2.3.0 524 * 525 * @param null|string $args If string, first parameter must be query statement 526 * @param mixed $args,... If additional parameters, they will be set inserted into the query. 527 * @return null|string Sanitized query string 528 */ 529 function prepare($query = null) { 530 if ( is_null( $query ) ) { 531 return; 532 } 533 $this->prepare_args = func_get_args(); 534 array_shift($this->prepare_args); 535 // If args were passed as an array (as in vsprintf), move them up 536 if ( isset($this->prepare_args[0]) && is_array($this->prepare_args[0]) ) { 537 $this->prepare_args = $this->prepare_args[0]; 538 } 539 $flag = '--PREPARE'; 540 foreach($this->prepare_args as $key => $arg){ 541 if ($key !== 0 && is_serialized($arg)) { 542 $flag = '--SERIALIZED'; 543 } 544 } 545 $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it 546 $query = str_replace('"%s"', '%s', $query); // doublequote unquoting 547 $query = str_replace('%s', "'%s'", $query); // quote the strings 548 array_walk($this->prepare_args, array(&$this, 'escape_by_ref')); 549 return @vsprintf($query, $this->prepare_args).$flag; 550 } 551 552 /** 553 * Print SQL/DB error. 554 * 555 * @since 0.71 556 * @global array $EZSQL_ERROR Stores error information of query and error string 557 * 558 * @param string $str The error to display 559 * @return bool False if the showing of errors is disabled. 560 */ 561 function print_error($str = '') { 562 global $EZSQL_ERROR; 563 564 if (!$str) { 565 $str = mssql_get_last_message(); 566 } 567 $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str); 568 569 if ( $this->suppress_errors ) 570 return false; 571 572 if ( $caller = $this->get_caller() ) 573 $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); 574 else 575 $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); 576 577 $log_error = true; 578 if ( ! function_exists('error_log') ) 579 $log_error = false; 580 581 $log_file = @ini_get('error_log'); 582 if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) ) 583 $log_error = false; 584 585 if ( $log_error ) 586 @error_log($error_str, 0); 587 588 // Is error output turned on or not.. 589 if ( !$this->show_errors ) 590 return false; 591 592 $str = htmlspecialchars($str, ENT_QUOTES); 593 $query = htmlspecialchars($this->last_query, ENT_QUOTES); 594 595 // If there is an error then take note of it 596 print "<div id='error'> 597 <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br /> 598 <code>$query</code></p> 599 </div>"; 600 } 601 602 /** 603 * Enables showing of database errors. 604 * 605 * This function should be used only to enable showing of errors. 606 * wpdb::hide_errors() should be used instead for hiding of errors. However, 607 * this function can be used to enable and disable showing of database 608 * errors. 609 * 610 * @since 0.71 611 * 612 * @param bool $show Whether to show or hide errors 613 * @return bool Old value for showing errors. 614 */ 615 function show_errors( $show = true ) { 616 $errors = $this->show_errors; 617 $this->show_errors = $show; 618 return $errors; 619 } 620 621 /** 622 * Disables showing of database errors. 623 * 624 * @since 0.71 625 * 626 * @return bool Whether showing of errors was active or not 627 */ 628 function hide_errors() { 629 $show = $this->show_errors; 630 $this->show_errors = false; 631 return $show; 632 } 633 634 /** 635 * Whether to suppress database errors. 636 * 637 * @param unknown_type $suppress 638 * @return unknown 639 */ 640 function suppress_errors( $suppress = true ) { 641 $errors = $this->suppress_errors; 642 $this->suppress_errors = $suppress; 643 return $errors; 644 } 645 646 /** 647 * Kill cached query results. 648 * 649 * @since 0.71 650 */ 651 function flush() { 652 $this->last_result = array(); 653 $this->col_info = null; 654 $this->last_query = null; 655 } 656 657 /** 658 * Perform a MSSQL database query, using current database connection. 659 * 660 * More information can be found on the codex page. 661 * 662 * @since 0.71 663 * 664 * @param string $query 665 * @param bool $translate Should we translate the query? 666 * @return int|false Number of rows affected/selected or false on error 667 */ 668 function query($query, $translate = true) { 669 670 if ( ! $this->ready ) { 671 return false; 672 } 673 674 // filter the query, if filters are available 675 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method 676 if ( function_exists('apply_filters') ) { 677 $query = apply_filters('query', $query); 678 } 679 680 // initialise return 681 $return_val = 0; 682 $this->flush(); 683 684 // Log how the function was called 685 $this->func_call = "\$db->query(\"$query\")"; 686 687 // Keep track of the last query for debug.. 688 $this->last_query = $query; 689 690 // Make Necessary Translations 691 if ($translate === true) { 692 $query = $this->translate($query); 693 $this->previous_query = $query; 694 } 695 696 if ($this->preceeding_query !== false) { 697 if (is_array($this->preceeding_query)) { 698 foreach ($this->preceeding_query as $p_query) { 699 @mssql_query($sub_query); 700 } 701 } else { 702 @mssql_query($this->preceeding_query); 703 } 704 $this->preceeding_query = false; 705 } 706 707 // Check if array of queries (this happens for INSERTS with multiple VALUES blocks) 708 if (is_array($query)) { 709 foreach ($query as $sub_query) { 710 $this->_pre_query(); 711 $this->result = @mssql_query($sub_query); 712 $return_val = $this->_post_query($sub_query); 713 } 714 } else { 715 $this->_pre_query(); 716 $this->result = @mssql_query(($query); 717 $return_val = $this->_post_query($query); 718 } 719 720 if ($this->following_query !== false) { 721 if (is_array($this->following_query)) { 722 foreach ($this->following_query as $f_query) { 723 @mssql_query($f_query); 724 } 725 } else { 726 @mssql_query($this->following_query); 727 } 728 $this->following_query = false; 729 } 730 731 return $return_val; 732 } 733 734 function _pre_query() { 735 if ( defined('SAVEQUERIES') && SAVEQUERIES ) { 736 $this->timer_start(); 737 } 738 } 739 740 function _post_query($query) { 741 ++$this->num_queries; 742 // If there is an error then take note of it.. 743 if ( $this->result == FALSE && $this->last_error = mssql_get_last_message() ) { 744 //var_dump($query); 745 //var_dump($this->translation_changes); 746 $this->print_error(); 747 return false; 748 } 749 750 if ( defined('SAVEQUERIES') && SAVEQUERIES ) { 751 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); 752 } 753 754 if ( preg_match("/^\\s*(insert|delete|update|replace) /i",$query) ) { 755 756 $this->rows_affected = mssql_rows_affected($this->dbh); 757 // Take note of the insert_id 758 if ( preg_match("/^\\s*(insert|replace) /i",$query) ) { 759 $result = @mssql_fetch_object(@mssql_query("SELECT SCOPE_IDENTITY() AS ID")); 760 $this->insert_id = $result->ID; 761 } 762 763 $return_val = $this->rows_affected; 764 } else { 765 766 $i = 0; 767 while ($i < @mssql_num_fields($this->result)) { 768 $field = @mssql_fetch_field($this->result, $i); 769 $new_field = new stdClass(); 770 $new_field->name = $field->name; 771 $new_field->table = $field->column_source; 772 $new_field->def = null; 773 $new_field->max_length = $field->max_length; 774 $new_field->not_null = true; 775 $new_field->primary_key = null; 776 $new_field->unique_key = null; 777 $new_field->multiple_key = null; 778 $new_field->numeric = $field->numeric; 779 $new_field->blob = null; 780 $new_field->type = $field->type; 781 if(isset($field->unsigned)) { 782 $new_field->unsigned = $field->unsigned; 783 } else { 784 $new_field->unsigned = null; 785 } 786 $new_field->zerofill = null; 787 $this->col_info[$i] = $new_field; 788 $i++; 789 } 790 $num_rows = 0; 791 while ( $row = @mssql_fetch_object($this->result) ) { 792 $this->last_result[$num_rows] = $row; 793 $num_rows++; 794 } 795 $this->last_result = $this->fix_results($this->last_result); 796 797 @mssql_free_result($this->result); 798 799 // Log number of rows the query returned 800 $this->num_rows = $num_rows; 801 802 // Return number of rows selected 803 $return_val = $this->num_rows; 804 } 805 806 return $return_val; 807 } 808 809 /** 810 * Insert a row into a table. 811 * 812 * <code> 813 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) 814 * </code> 815 * 816 * @since 2.5.0 817 * @see wpdb::prepare() 818 * 819 * @param string $table table name 820 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 821 * @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. 822 * @return int|false The number of rows inserted, or false on error. 823 */ 824 function insert($table, $data, $format = null) { 825 $formats = $format = (array) $format; 826 $fields = array_keys($data); 827 $formatted_fields = array(); 828 foreach ( $fields as $field ) { 829 if ( !empty($format) ) 830 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 831 elseif ( isset($this->field_types[$field]) ) 832 $form = $this->field_types[$field]; 833 else 834 $form = '%s'; 835 $formatted_fields[] = $form; 836 } 837 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')"; 838 return $this->query( $this->prepare( $sql, $data) ); 839 } 840 841 /** 842 * Update a row in the table 843 * 844 * <code> 845 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) 846 * </code> 847 * 848 * @since 2.5.0 849 * @see wpdb::prepare() 850 * 851 * @param string $table table name 852 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 853 * @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". 854 * @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. 855 * @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. 856 * @return int|false The number of rows updated, or false on error. 857 */ 858 function update($table, $data, $where, $format = null, $where_format = null) { 859 if ( !is_array( $where ) ) 860 return false; 861 862 $formats = $format = (array) $format; 863 $bits = $wheres = array(); 864 foreach ( (array) array_keys($data) as $field ) { 865 if ( !empty($format) ) 866 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 867 elseif ( isset($this->field_types[$field]) ) 868 $form = $this->field_types[$field]; 869 else 870 $form = '%s'; 871 $bits[] = "`$field` = {$form}"; 872 } 873 874 $where_formats = $where_format = (array) $where_format; 875 foreach ( (array) array_keys($where) as $field ) { 876 if ( !empty($where_format) ) 877 $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0]; 878 elseif ( isset($this->field_types[$field]) ) 879 $form = $this->field_types[$field]; 880 else 881 $form = '%s'; 882 $wheres[] = "`$field` = {$form}"; 883 } 884 885 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ); 886 return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) ); 887 } 888 889 /** 890 * Retrieve one variable from the database. 891 * 892 * This combines the functionality of wpdb::get_row() and wpdb::get_col(), 893 * so both the column and row can be picked. 894 * 895 * It is possible to use this function without executing more queries. If 896 * you already made a query, you can set the $query to 'null' value and just 897 * retrieve either the column and row of the last query result. 898 * 899 * @since 0.71 900 * 901 * @param string $query Can be null as well, for caching 902 * @param int $x Column num to return 903 * @param int $y Row num to return 904 * @return mixed Database query results 905 */ 906 function get_var($query=null, $x = 0, $y = 0) { 907 $this->func_call = "\$db->get_var(\"$query\",$x,$y)"; 908 if ( $query ) 909 $this->query($query); 910 911 // Extract var out of cached results based x,y vals 912 if ( !empty( $this->last_result[$y] ) ) { 913 $values = array_values(get_object_vars($this->last_result[$y])); 914 } 915 916 // If there is a value return it else return null 917 return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null; 918 } 919 920 /** 921 * Retrieve one row from the database. 922 * 923 * @since 0.71 924 * 925 * @param string $query SQL query 926 * @param string $output ARRAY_A | ARRAY_N | OBJECT 927 * @param int $y Row num to return 928 * @return mixed Database query results 929 */ 930 function get_row($query = null, $output = OBJECT, $y = 0) { 931 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; 932 if ( $query ) 933 $this->query($query); 934 else 935 return null; 936 937 if ( !isset($this->last_result[$y]) ) 938 return null; 939 940 if ( $output == OBJECT ) { 941 return $this->last_result[$y] ? $this->last_result[$y] : null; 942 } elseif ( $output == ARRAY_A ) { 943 return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null; 944 } elseif ( $output == ARRAY_N ) { 945 return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null; 946 } else { 947 $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*/); 948 } 949 } 950 951 /** 952 * Retrieve one column from the database. 953 * 954 * @since 0.71 955 * 956 * @param string $query Can be null as well, for caching 957 * @param int $x Col num to return. Starts from 0. 958 * @return array Column results 959 */ 960 function get_col($query = null , $x = 0) { 961 if ( $query ) 962 $this->query($query); 963 964 $new_array = array(); 965 // Extract the column values 966 for ( $i=0; $i < count($this->last_result); $i++ ) { 967 $new_array[$i] = $this->get_var(null, $x, $i); 968 } 969 return $new_array; 970 } 971 972 /** 973 * Retrieve an entire result set from the database. 974 * 975 * @since 0.71 976 * 977 * @param string|null $query Can also be null to pull from the cache 978 * @param string $output ARRAY_A | ARRAY_N | OBJECT_K | OBJECT 979 * @return mixed Database query results 980 */ 981 function get_results($query = null, $output = OBJECT) { 982 $this->func_call = "\$db->get_results(\"$query\", $output)"; 983 984 if ( $query ) 985 $this->query($query); 986 else 987 return null; 988 989 if ( $output == OBJECT ) { 990 // Return an integer-keyed array of row objects 991 return $this->last_result; 992 } elseif ( $output == OBJECT_K ) { 993 // Return an array of row objects with keys from column 1 994 // (Duplicates are discarded) 995 foreach ( $this->last_result as $row ) { 996 $key = array_shift( get_object_vars( $row ) ); 997 if ( !isset( $new_array[ $key ] ) ) 998 $new_array[ $key ] = $row; 999 } 1000 return $new_array; 1001 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { 1002 // Return an integer-keyed array of... 1003 if ( $this->last_result ) { 1004 $i = 0; 1005 foreach( (array) $this->last_result as $row ) { 1006 if ( $output == ARRAY_N ) { 1007 // ...integer-keyed row arrays 1008 $new_array[$i] = array_values( get_object_vars( $row ) ); 1009 } else { 1010 // ...column name-keyed row arrays 1011 $new_array[$i] = get_object_vars( $row ); 1012 } 1013 ++$i; 1014 } 1015 return $new_array; 1016 } 1017 } 1018 } 1019 1020 /** 1021 * Retrieve column metadata from the last query. 1022 * 1023 * @since 0.71 1024 * 1025 * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill 1026 * @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 1027 * @return mixed Column Results 1028 */ 1029 function get_col_info($info_type = 'name', $col_offset = -1) { 1030 if ( $this->col_info ) { 1031 if ( $col_offset == -1 ) { 1032 $i = 0; 1033 foreach( (array) $this->col_info as $col ) { 1034 $new_array[$i] = $col->{$info_type}; 1035 $i++; 1036 } 1037 return $new_array; 1038 } else { 1039 return $this->col_info[$col_offset]->{$info_type}; 1040 } 1041 } 1042 } 1043 1044 /** 1045 * Starts the timer, for debugging purposes. 1046 * 1047 * @since 1.5.0 1048 * 1049 * @return bool Always returns true 1050 */ 1051 function timer_start() { 1052 $mtime = microtime(); 1053 $mtime = explode(' ', $mtime); 1054 $this->time_start = $mtime[1] + $mtime[0]; 1055 return true; 1056 } 1057 1058 /** 1059 * Stops the debugging timer. 1060 * 1061 * @since 1.5.0 1062 * 1063 * @return int Total time spent on the query, in milliseconds 1064 */ 1065 function timer_stop() { 1066 $mtime = microtime(); 1067 $mtime = explode(' ', $mtime); 1068 $time_end = $mtime[1] + $mtime[0]; 1069 $time_total = $time_end - $this->time_start; 1070 return $time_total; 1071 } 1072 1073 /** 1074 * Wraps fatal errors in a nice header and footer and dies. 1075 * 1076 * @since 1.5.0 1077 * 1078 * @param string $message 1079 * @return unknown 1080 */ 1081 function bail($message) { 1082 if ( !$this->show_errors ) { 1083 if ( class_exists('WP_Error') ) 1084 $this->error = new WP_Error('500', $message); 1085 else 1086 $this->error = $message; 1087 return false; 1088 } 1089 wp_die($message); 1090 } 1091 1092 /** 1093 * Whether or not MySQL database is minimal required version. 1094 * 1095 * @since 2.5.0 1096 * @uses $wp_version 1097 * 1098 * @return WP_Error 1099 */ 1100 function check_database_version() 1101 { 1102 global $wp_version; 1103 // Base on database type 1104 // 1105 if ($this->db_type == "mysql") { 1106 // Make sure the server has MySQL 4.0 1107 $mysql_version = preg_replace('|[^0-9\.]|', '', @mysql_get_server_info($this->dbh)); 1108 if ( version_compare($mysql_version, '4.0.0', '<') ) 1109 return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version)); 1110 } 1111 } 1112 1113 /** 1114 * Whether of not the database version supports collation. 1115 * 1116 * Called when WordPress is generating the table scheme. 1117 * 1118 * @since 2.5.0 1119 * 1120 * @return bool True if collation is supported, false if version does not 1121 */ 1122 function supports_collation() 1123 { 1124 return false; 1125 } 1126 1127 /** 1128 * Retrieve the name of the function that called wpdb. 1129 * 1130 * Requires PHP 4.3 and searches up the list of functions until it reaches 1131 * the one that would most logically had called this method. 1132 * 1133 * @since 2.5.0 1134 * 1135 * @return string The name of the calling function 1136 */ 1137 function get_caller() { 1138 // requires PHP 4.3+ 1139 if ( !is_callable('debug_backtrace') ) 1140 return ''; 1141 1142 $bt = debug_backtrace(); 1143 $caller = array(); 1144 1145 $bt = array_reverse( $bt ); 1146 foreach ( (array) $bt as $call ) { 1147 if ( @$call['class'] == __CLASS__ ) 1148 continue; 1149 $function = $call['function']; 1150 if ( isset( $call['class'] ) ) 1151 $function = $call['class'] . "->$function"; 1152 $caller[] = $function; 1153 } 1154 $caller = join( ', ', $caller ); 1155 1156 return $caller; 1157 } 1158 1159 function show_tables() 1160 { 1161 $tables = $this->get_col("Select Table_name as \"Table name\" 1162 From Information_schema.Tables 1163 Where Table_type = 'BASE TABLE' and Objectproperty 1164 (Object_id(Table_name), 'IsMsShipped') = 0"); 1165 foreach ($tables as $table) { 1166 echo "Table: ".$table."<br/>"; 1167 $rows = $this->get_col("SELECT COUNT (*) FROM {$table}"); 1168 foreach ($rows as $row) { 1169 echo "Rows: ".$row."<br/>"; 1170 } 1171 } 1172 } 1173 } 1174 No newline at end of file -
wp-includes/wp-db/mssql/translations/fields_map.php
Property changes on: wp-includes\wp-db\mssql\mssql.php ___________________________________________________________________ Added: svn:eol-style + native
1 <?php 2 /** 3 * Fields mapping 4 * 5 * Some column types from MySQL 6 * don't have an exact equivalent for SQL Server 7 * That is why we need to know what column types they were 8 * originally to make the translations. 9 * 10 * @category MSSQL 11 * @package MySQL_Translations 12 * @author A.Garcia & A.Gentile 13 * */ 14 class Fields_map 15 { 16 var $fields_map = array(); 17 var $filepath = ''; 18 19 /** 20 * php4 style call to constructor. 21 * 22 * @since 2.7.1 23 * 24 */ 25 function Fields_map() 26 { 27 return $this->__construct(); 28 } 29 30 /** 31 * Set filepath 32 * 33 * PHP5 style constructor for compatibility with PHP5. 34 * 35 * @since 2.7.1 36 */ 37 function __construct() 38 { 39 $this->filepath = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/wp-content/fields_map.parsed_types.php'; 40 } 41 42 /** 43 * Get array of fields by type from fields_map property 44 * 45 * @since 2.8 46 * @param $type 47 * @param $table 48 * 49 * @return array 50 */ 51 function by_type($type, $table = null) 52 { 53 $ret = array(); 54 foreach ( $this->fields_map as $tables => $fields ) { 55 if ( is_array($fields) ) { 56 foreach ( $fields as $field_name => $field_meta ) { 57 if ( $field_meta['type'] == $type ) { 58 if ( is_null($table) || $tables == $table ) { 59 $ret[] = $field_name; 60 } 61 } 62 } 63 } 64 } 65 return $ret; 66 } 67 68 /** 69 * Get array of tables from fields_map property 70 * 71 * @since 2.8 72 * 73 * @return array 74 */ 75 function get_tables() 76 { 77 $ret = array(); 78 foreach ( $this->fields_map as $tables => $fields ) { 79 $ret[] = $tables; 80 } 81 return $ret; 82 } 83 84 /** 85 * Given a query find the column types 86 * 87 * @since 2.8 88 * @param $qry 89 * 90 * @return array 91 */ 92 function extract_column_types($qry) 93 { 94 //table name 95 $matches = array(); 96 if ( preg_match('/(?:CREATE|ALTER) TABLE (.*) \(/i', $qry, $matches) ) { 97 $table_name = $matches[1]; 98 } else { 99 $table_name = ''; 100 } 101 102 103 $fields_and_indexes = substr( $qry, strpos($qry, '(') + 1, strrpos($qry, ')') - (strpos($qry, '(') + 1) ); 104 $just_fields = trim( substr( $fields_and_indexes, 0, $this->index_pos($fields_and_indexes) ) ); 105 106 $field_lines = explode(',', $just_fields); 107 $field_types = array(); 108 foreach ( $field_lines as $field_line ) { 109 if ( !empty($field_line) ) { 110 $field_line = trim($field_line); 111 $words = explode(' ', $field_line, 3); 112 $first_word = $words[0]; 113 $field_type = $this->type_translations($words[1]); 114 if ( $field_type !== false ) { 115 $field_types[$first_word] = array('type'=>$field_type); 116 } 117 } 118 } 119 120 //get primary key 121 $just_indexes = trim( substr( $fields_and_indexes, $this->index_pos($fields_and_indexes) ) ); 122 $matches = array(); 123 $has_primary_key = preg_match('/PRIMARY KEY *\((.*?)[,|\)]/i', $just_indexes, $matches); 124 if ( $has_primary_key ) { 125 $primary_key = trim($matches[1]); 126 $field_types[$primary_key] = array('type' => 'primary_id'); 127 } 128 ksort($field_types); 129 130 return array($table_name => $field_types); 131 } 132 133 /** 134 * According to the column types in MySQL 135 * 136 * @since 2.8 137 * @param $field_type 138 * 139 * @return array 140 */ 141 function type_translations($field_type) 142 { 143 //false means not translate this field. 144 $translations = array( 145 array('pattern' => '/varchar(.*)/', 'trans' => false), 146 array('pattern' => '/.*text.*/', 'trans' => 'text'), 147 array('pattern' => '/.*datetime.*/','trans' => 'date'), 148 array('pattern' => '/int(.*)/', 'trans' => 'int'), 149 ); 150 151 $res = ''; 152 while ( ($res === '') && ($trans = array_shift($translations)) ) { 153 if ( preg_match($trans['pattern'],$field_type) ) { 154 $res = $trans['trans']; 155 } 156 } 157 158 if ( $res === '' ) { 159 $res = $field_type; 160 } 161 return $res; 162 } 163 164 165 /** 166 * Get array of tables from fields_map property 167 * 168 * @since 2.8 169 * @param $fields_and_indexes 170 * 171 * @return array 172 */ 173 function index_pos($fields_and_indexes) 174 { 175 $reserved_words = array('PRIMARY KEY', 'UNIQUE'); 176 $res = false; 177 while ( ($res === false) && ($reserved_word = array_shift($reserved_words)) ){ 178 $res = stripos($fields_and_indexes,$reserved_word); 179 } 180 181 return $res; 182 } 183 184 /** 185 * Update fields may given a CREATE | ALTER query 186 * 187 * @since 2.8 188 * @param $qry 189 * 190 * @return array 191 */ 192 function update_for($qry) 193 { 194 $this->read(); 195 $this->fields_map = array_merge($this->fields_map, $this->extract_column_types($qry)); 196 file_put_contents($this->filepath, '<?php return ' . var_export($this->fields_map, true) . "\n ?>"); 197 return $this->fields_map; 198 } 199 200 /** 201 * Get the fields_map from memory or from the file. 202 * 203 * @since 2.8 204 * 205 * @return array 206 */ 207 function read() 208 { 209 if ( empty($this->fields_map) ) { 210 if ( file_exists($this->filepath) ) { 211 $this->fields_map = require($this->filepath); 212 } else { 213 $this->fields_map = array(); 214 } 215 } 216 return $this->fields_map; 217 } 218 219 } -
wp-includes/wp-db/mssql/translations/translations.php
Property changes on: wp-includes\wp-db\mssql\translations\fields_map.php ___________________________________________________________________ Added: svn:eol-style + native
1 <?php 2 require_once(dirname(__FILE__) . '/fields_map.php'); 3 4 /** 5 * SQL Dialect Translations 6 * 7 * @category MSSQL 8 * @package MySQL_Translations 9 * @author A.Garcia & A.Gentile 10 * */ 11 class SQL_Translations 12 { 13 /** 14 * Field Mapping 15 * 16 * @since 2.7.1 17 * @access private 18 * @var array 19 */ 20 var $fields_map = null; 21 22 /** 23 * Was this query prepared? 24 * 25 * @since 2.7.1 26 * @access private 27 * @var bool 28 */ 29 var $prepared = false; 30 31 /** 32 * Update query? 33 * 34 * @since 2.7.1 35 * @access private 36 * @var bool 37 */ 38 var $update_query = false; 39 40 /** 41 * Insert query? 42 * 43 * @since 2.7.1 44 * @access private 45 * @var bool 46 */ 47 var $insert_query = false; 48 49 /** 50 * Prepare arguments 51 * 52 * @since 2.7.1 53 * @access private 54 * @var array 55 */ 56 var $prepare_args = array(); 57 58 /** 59 * Update Data 60 * 61 * @since 2.7.1 62 * @access private 63 * @var array 64 */ 65 var $update_data = array(); 66 67 /** 68 * Update Data 69 * 70 * @since 2.7.1 71 * @access private 72 * @var array 73 */ 74 var $translation_changes = array(); 75 76 /** 77 * Azure 78 * Are we dealing with a SQL Azure DB? 79 * 80 * @since 2.7.1 81 * @access public 82 * @var bool 83 */ 84 var $azure = false; 85 86 /** 87 * Preceeding query 88 * Sometimes we need to issue a query 89 * before the original query 90 * 91 * @since 2.8.5 92 * @access public 93 * @var mixed 94 */ 95 var $preceeding_query = false; 96 97 /** 98 * Following query 99 * Sometimes we need to issue a query 100 * right after the original query 101 * 102 * @since 2.8.5 103 * @access public 104 * @var mixed 105 */ 106 var $following_query = false; 107 108 /** 109 * php4 style call to constructor. 110 * 111 * @since 2.7.1 112 * 113 */ 114 function SQL_Translations() 115 { 116 return $this->__construct(); 117 } 118 119 /** 120 * Assign fields_map as a new Fields_map object 121 * 122 * PHP5 style constructor for compatibility with PHP5. 123 * 124 * @since 2.7.1 125 */ 126 function __construct() 127 { 128 $this->fields_map = new Fields_map(); 129 } 130 131 /** 132 * MySQL > MSSQL Query Translation 133 * Processes smaller translation sub-functions 134 * 135 * @since 2.7.1 136 * 137 * @param string $query Query coming in 138 * 139 * @return string Translated Query 140 */ 141 function translate($query) 142 { 143 $this->insert_query = false; 144 $this->preceeding_query = false; 145 $this->following_query = false; 146 147 if ( stripos($query, 'INSERT') === 0 ) { 148 $this->insert_query = true; 149 } 150 151 // Was this query prepared? 152 if ( strripos($query, '--PREPARE') !== FALSE ) { 153 $query = str_replace('--PREPARE', '', $query); 154 $this->prepared = TRUE; 155 } else { 156 $this->prepared = FALSE; 157 } 158 159 // Update Query? 160 if ( strripos($query, '--UPDATE') !== FALSE ) { 161 $query = str_replace('--UPDATE', '', $query); 162 $this->update_query = TRUE; 163 } else { 164 $this->update_query = FALSE; 165 } 166 167 // Do we have serialized arguments? 168 if ( strripos($query, '--SERIALIZED') !== FALSE ) { 169 $query = str_replace('--SERIALIZED', '', $query); 170 $query = $this->translate_general($query); 171 return $query; 172 } 173 174 $query = trim($query); 175 176 $sub_funcs = array( 177 'translate_general', 178 'translate_date_add', 179 'translate_if_stmt', 180 'translate_sqlcalcrows', 181 'translate_limit', 182 'translate_now_datetime', 183 'translate_distinct_orderby', 184 'translate_sort_casting', 185 'translate_column_type', 186 'translate_remove_groupby', 187 'translate_insert_nulltime', 188 'translate_incompat_data_type', 189 'translate_create_queries', 190 ); 191 192 // Perform translations and record query changes. 193 $this->translation_changes = array(); 194 foreach ( $sub_funcs as $sub_func ) { 195 $old_query = $query; 196 $query = $this->$sub_func($query); 197 if ( $old_query !== $query ) { 198 $this->translation_changes[] = $sub_func; 199 $this->translation_changes[] = $query; 200 $this->translation_changes[] = $old_query; 201 } 202 } 203 if ( $this->insert_query ) { 204 $query = $this->split_insert_values($query); 205 } 206 if ( $this->prepared && $this->insert_query ) { 207 if ( is_array($query) ) { 208 foreach ($query as $k => $v) { 209 $query[$k] = $this->verify_insert($v); 210 } 211 } else { 212 $query = $this->verify_insert($query); 213 } 214 } 215 216 if ( $this->update_query ) { 217 $query = $this->verify_update($query); 218 } 219 220 return $query; 221 } 222 223 /** 224 * More generalized information gathering queries 225 * 226 * @since 2.7.1 227 * 228 * @param string $query Query coming in 229 * 230 * @return string Translated Query 231 */ 232 function translate_general($query) 233 { 234 // SERVER VERSION 235 if ( stripos($query, 'SELECT VERSION()' ) === 0 ) { 236 $query = substr_replace($query, 'SELECT @@VERSION', 0, 16); 237 } 238 // SQL_MODE NO EQUIV 239 if ( stripos($query, "SHOW VARIABLES LIKE 'sql_mode'" ) === 0 ) { 240 $query = ''; 241 } 242 // LAST INSERT ID 243 if ( stripos($query, 'LAST_INSERT_ID()') > 0 ) { 244 $start_pos = stripos($query, 'LAST_INSERT_ID()'); 245 $query = substr_replace($query, '@@IDENTITY', $start_pos, 16); 246 } 247 // SHOW TABLES 248 if ( strtolower($query) === 'show tables;' ) { 249 $query = str_ireplace('show tables', "select name from SYSOBJECTS where TYPE = 'U' order by NAME", $query); 250 } 251 if ( stripos($query, 'show tables like ') === 0 ) { 252 $end_pos = strlen($query); 253 $param = substr($query, 17, $end_pos - 17); 254 $query = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ' . $param; 255 } 256 // SET NAMES doesn't exist in T-SQL 257 if ( strtolower($query) == "set names 'utf8'" ) { 258 $query = ""; 259 } 260 // SHOW COLUMNS 261 if ( stripos($query, 'SHOW COLUMNS FROM ') === 0 ) { 262 $end_pos = strlen($query); 263 $param = substr($query, 18, $end_pos - 18); 264 $param = "'". trim($param, "'") . "'"; 265 $query = 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ' . $param; 266 } 267 268 // SHOW INDEXES - issue with sql azure trying to fix....sys.sysindexes is coming back as invalid onject name 269 if ( stripos($query, 'SHOW INDEXES FROM ') === 0 ) { 270 return $query; 271 $table = substr($query, 18); 272 $query = "SELECT sys.sysindexes.name AS IndexName 273 FROM sysobjects 274 JOIN sys.key_constraints ON parent_object_id = sys.sysobjects.id 275 JOIN sys.sysindexes ON sys.sysindexes.id = sys.sysobjects.id and sys.key_constraints.unique_index_id = sys.sysindexes.indid 276 JOIN sys.index_columns ON sys.index_columns.object_id = sys.sysindexes.id and sys.index_columns.index_id = sys.sysindexes.indid 277 JOIN sys.syscolumns ON sys.syscolumns.id = sys.sysindexes.id AND sys.index_columns.column_id = sys.syscolumns.colid 278 WHERE sys.sysobjects.type = 'u' 279 AND sys.sysobjects.name = '{$table}'"; 280 } 281 282 // USE INDEX 283 if ( stripos($query, 'USE INDEX (') !== FALSE ) { 284 $start_pos = stripos($query, 'USE INDEX ('); 285 $end_pos = $this->get_matching_paren($query, $start_pos + 11); 286 $params = substr($query, $start_pos + 11, $end_pos - ($start_pos + 11)); 287 $params = explode(',', $params); 288 foreach ( $params as $k => $v ) { 289 $params[$k] = trim($v); 290 foreach ( $this->fields_map->read() as $table => $fields ) { 291 if ( is_array($fields) ) { 292 foreach ( $fields as $field_name => $field_meta ) { 293 if ( $field_name == $params[$k] ) { 294 $params[$k] = $table . '_' . $params[$k]; 295 } 296 } 297 } 298 } 299 } 300 $params = implode(',', $params); 301 $query = substr_replace($query, 'WITH (INDEX(' . $params . '))', $start_pos, ($end_pos + 1) - $start_pos); 302 } 303 304 // DESCRIBE - this is pretty darn close to mysql equiv, however it will need to have a flag to modify the result set 305 // this and SHOW INDEX FROM are used in WP upgrading. The problem is that WP will see the different data types and try 306 // to alter the table thinking an upgrade is necessary. So the result set from this query needs to be modified using 307 // the field_mapping to revert column types back to their mysql equiv to fool WP. 308 if ( stripos($query, 'DESCRIBE ') === 0 ) { 309 return $query; 310 $table = substr($query, 9); 311 $query = $this->describe($table); 312 } 313 314 // DROP TABLES 315 if ( stripos($query, 'DROP TABLE IF EXISTS ') === 0 ) { 316 $table = substr($query, 21, strlen($query) - 21); 317 $query = 'DROP TABLE ' . $table; 318 } elseif ( stripos($query, 'DROP TABLE ') === 0 ) { 319 $table = substr($query, 11, strlen($query) - 11); 320 $query = 'DROP TABLE ' . $table; 321 } 322 323 // TICKS 324 $query = str_replace('`', '', $query); 325 326 // Computed 327 // This is done as the SQLSRV driver doesn't seem to set a property value for computed 328 // selected columns, thus WP doesn't have anything to work with. 329 $query = str_replace('SELECT COUNT(*)', 'SELECT COUNT(*) as Computed', $query); 330 331 // Turn on IDENTITY_INSERT for Importing inserts that are trying to explicitly set 332 // and IDENTITY column 333 if ( $this->insert_query ) { 334 if ( stristr($query, 'INTO ' . $this->prefix . 'posts') !== FALSE ) { 335 $strlen = strlen($this->prefix . 'posts'); 336 $start_pos = stripos($query, $this->prefix . 'posts') + $strlen; 337 $start_pos = stripos($query, '(', $start_pos); 338 $end_pos = $this->get_matching_paren($query, $start_pos + 1); 339 $params = substr($query, $start_pos + 1, $end_pos - ($start_pos + 1)); 340 $params = explode(',', $params); 341 $found = false; 342 foreach ( $params as $k => $v ) { 343 if ( strtolower($v) === 'id' ) { 344 $found = true; 345 } 346 } 347 if ( $found ) { 348 $this->preceeding_query = "SET IDENTITY_INSERT {$this->prefix}posts ON"; 349 $this->following_query = "SET IDENTITY_INSERT {$this->prefix}posts OFF"; 350 } 351 } 352 } 353 354 return $query; 355 } 356 357 358 /** 359 * Changes for DATE_ADD and INTERVAL 360 * 361 * @since 2.7.1 362 * 363 * @param string $query Query coming in 364 * 365 * @return string Translated Query 366 */ 367 function translate_date_add($query) 368 { 369 $query = preg_replace('/date_add\((.*?),.*?([0-9]+?) (.*?)\)/i', 'DATEADD(\3,\2,\1)', $query); 370 $query = preg_replace('/date_sub\((.*?),.*?([0-9]+?) (.*?)\)/i', 'DATEADD(\3,-\2,\1)', $query); 371 372 return $query; 373 } 374 375 376 /** 377 * Removing Unnecessary IF statement that T-SQL doesn't play nice with 378 * 379 * @since 2.7.1 380 * 381 * @param string $query Query coming in 382 * 383 * @return string Translated Query 384 */ 385 function translate_if_stmt($query) 386 { 387 if ( stripos( $query, 'IF (DATEADD(') > 0 ) { 388 $start_pos = stripos($query, 'DATEADD('); 389 $end_pos = $this->get_matching_paren($query, $start_pos + 8); 390 $stmt = substr($query, $start_pos, ($end_pos - $start_pos)) . ') >= getdate() THEN 1 ELSE 0 END)'; 391 392 $start_pos = stripos($query, 'IF ('); 393 $end_pos = $this->get_matching_paren($query, ($start_pos+6))+1; 394 $query = substr_replace($query, '(CASE WHEN ' . $stmt, $start_pos, ($end_pos - $start_pos)); 395 } 396 return $query; 397 } 398 399 /** 400 * SQL_CALC_FOUND_ROWS does not exist in T-SQL 401 * 402 * @since 2.7.1 403 * 404 * @param string $query Query coming in 405 * 406 * @return string Translated Query 407 */ 408 function translate_sqlcalcrows($query) 409 { 410 if ( stripos($query, 'SQL_CALC_FOUND_ROWS') > 0 ) { 411 $sql_calc_pos = stripos($query, 'SQL_CALC_FOUND_ROWS'); 412 $from_pos = stripos($query, 'FROM'); 413 $query = substr_replace($query,'* ', $sql_calc_pos, ($from_pos - $sql_calc_pos)); 414 } 415 // catch the next query. 416 if ( stripos($query, 'FOUND_ROWS()') > 0 ) { 417 $from_pos = stripos($this->previous_query, 'FROM'); 418 $where_pos = stripos($this->previous_query, 'WHERE'); 419 $from_str = trim(substr($this->previous_query, $from_pos, ($where_pos - $from_pos))); 420 $order_by_pos = stripos($this->previous_query, 'ORDER BY'); 421 $where_str = trim(substr($this->previous_query, $where_pos, ($order_by_pos - $where_pos))); 422 $query = str_ireplace('FOUND_ROWS()', 'COUNT(1) ' . $from_str . ' ' . $where_str, $query); 423 } 424 return $query; 425 } 426 427 /** 428 * Changing LIMIT to TOP...mimicking offset 429 * 430 * @since 2.7.1 431 * 432 * @param string $query Query coming in 433 * 434 * @return string Translated Query 435 */ 436 function translate_limit($query) 437 { 438 if ( ( stripos($query,'SELECT') !== 0 && stripos($query,'SELECT') !== FALSE ) 439 && ( stripos($query,'UPDATE') !== 0 && stripos($query,'UPDATE') !== FALSE ) ) { 440 return $query; 441 } 442 $pattern = '/LIMIT\s*(\d+)((\s*,?\s*)(\d+)*)$/is'; 443 $matched = preg_match($pattern, $query, $limit_matches); 444 if ( $matched == 0 ) { 445 return $query; 446 } 447 // Remove the LIMIT statement 448 $true_offset = false; 449 $query = preg_replace($pattern, '', $query); 450 if ( stripos($query,'DELETE') === 0 ) { 451 return $query; 452 } 453 // Check for true offset 454 if ( count($limit_matches) == 5 && $limit_matches[1] != '0' ) { 455 $true_offset = true; 456 if ( stripos($query, 'SELECT DISTINCT') === 0 ) { 457 $start = 15; 458 $start_type = 'SELECT DISTINCT'; 459 } elseif ( stripos($query, 'SELECT') === 0 ) { 460 $start = 6; 461 $start_type = 'SELECT'; 462 } elseif ( stripos($query, 'DELETE') === 0 ) { 463 $start = 6; 464 $start_type = 'DELETE'; 465 } 466 // Grab any ORDER BY fields 467 $arr = array(); 468 if ( stripos($query, 'ORDER') > 0 ) { 469 $order_pos = stripos($query, 'ORDER'); 470 if ( stripos($query, 'BY', $order_pos) > $order_pos ) { 471 $true_offset = true; 472 $order_by_pos = stripos($query, 'BY', $order_pos) + 2; 473 $fields = substr($query, $order_by_pos, strlen($query) - $order_by_pos); 474 $query = substr_replace($query, '', $order_pos, strlen($query) - $order_pos); 475 $fields = explode(',', $fields); 476 foreach ( $fields as $field ) { 477 $field = trim($field); 478 if ( stripos($field, 'DESC') > 0 ) { 479 $pos = stripos($field, 'DESC'); 480 $field = trim(substr_replace($field, '', $pos, ($pos + 4) - $pos)); 481 $arr[] = array('field' => $field, 'ord' => 'DESC'); 482 } elseif ( stripos($field, 'ASC') > 0 ) { 483 $pos = stripos($field, 'ASC'); 484 $field = trim(substr_replace($field, '', $pos, ($pos + 3) - $pos)); 485 $arr[] = array('field' => $field, 'ord' => 'ASC'); 486 } else { 487 $arr[] = array('field' => $field, 'ord' => ''); 488 } 489 } 490 } 491 } 492 // Get table name from 'FROM' section. 493 $from_pos = stripos($query, 'FROM', $start); 494 $end_from = stripos($query, ' ', $from_pos + 5); 495 $table = substr($query, $from_pos + 5, $end_from - ($from_pos + 5)); 496 $sarr = explode( ',', trim( substr($query, $start, ($from_pos - $start)) ) ); 497 $tables = $this->fields_map->get_tables(); 498 if ( !in_array($table, $tables) ) { 499 // We can't continue without the primary key 500 $true_offset = false; 501 } 502 if ( $true_offset ) { 503 $primary_key = $this->fields_map->by_type('primary_id', $table); 504 $sarr[] = "ROW_NUMBER() OVER(ORDER BY " . $primary_key[0] . ") AS RowNum"; 505 $str = implode(', ', $sarr); 506 $query = substr_replace($query, $str . ' ', $start + 1, $from_pos - ($start + 1)); 507 } 508 509 } elseif ( count($limit_matches) == 5 && $limit_matches[1] == '0' ) { 510 $limit_matches[1] = $limit_matches[4]; 511 $true_offset = false; 512 } 513 514 // Rewrite the query. 515 if ( $true_offset === false ) { 516 if ( stripos($query, 'DISTINCT') > 0 ) { 517 $query = str_ireplace('DISTINCT', 'DISTINCT TOP ' . $limit_matches[1] . ' ', $query); 518 } else { 519 $query = str_ireplace('DELETE ', 'DELETE TOP ' . $limit_matches[1] . ' ', $query); 520 $query = str_ireplace('SELECT ', 'SELECT TOP ' . $limit_matches[1] . ' ', $query); 521 } 522 } else { 523 $limit_matches[1] = (int) $limit_matches[1]; 524 $limit_matches[4] = (int) $limit_matches[4]; 525 $q = ''; 526 foreach ( $arr as $order_by_field ) { 527 $q .= $order_by_field['field'].' '.$order_by_field['ord'].', '; 528 } 529 $q = ' ORDER BY ' . rtrim($q, ', '); 530 if ( stripos($query, 'DISTINCT') > 0 ) { 531 $query = 'SELECT * 532 FROM ( 533 '. $query . ' 534 ) AS DerivTable 535 WHERE DerivTable.RowNum BETWEEN ' . $limit_matches[1] . ' AND ' . ($limit_matches[1] + $limit_matches[4]) . $q; 536 } else { 537 $query = 'SELECT * 538 FROM ( 539 '. $query . ' 540 ) AS DerivTable 541 WHERE DerivTable.RowNum BETWEEN ' . $limit_matches[1] . ' AND ' . ($limit_matches[1] + $limit_matches[4]) . $q; 542 } 543 } 544 return $query; 545 } 546 547 548 /** 549 * Replace From UnixTime and now() 550 * 551 * @since 2.7.1 552 * 553 * @param string $query Query coming in 554 * 555 * @return string Translated Query 556 */ 557 function translate_now_datetime($query) 558 { 559 $replacement = 'getdate()'; 560 $query = preg_replace('/(from_unixtime|unix_timestamp)\s*\(([^\)]*)\)/i', $replacement, $query); 561 $query = str_ireplace('NOW()', $replacement, $query); 562 563 // REPLACE dayofmonth which doesn't exist in T-SQL 564 $check = $query; 565 $query = preg_replace('/dayofmonth\((.*?)\)/i', 'DATEPART(DD,\1)',$query); 566 if ( $check !== $query ) { 567 $as_array = $this->get_as_fields($query); 568 if ( empty($as_array) ) { 569 $query = str_ireplace('FROM', 'as dom FROM', $query); 570 } 571 } 572 return $query; 573 } 574 575 /** 576 * Order By within a Select Distinct needs to have an field for every alias 577 * 578 * @since 2.7.1 579 * 580 * @param string $query Query coming in 581 * 582 * @return string Translated Query 583 */ 584 function translate_distinct_orderby($query) 585 { 586 if ( stripos($query, 'DISTINCT') > 0 ) { 587 if ( stripos($query, 'ORDER') > 0 ) { 588 $order_pos = stripos($query, 'ORDER'); 589 if ( stripos($query, 'BY', $order_pos) > $order_pos ) { 590 $fields = $this->get_as_fields($query); 591 $ob = stripos($query, 'BY', $order_pos); 592 if ( stripos($query, ' ASC', $ob) > 0 ) { 593 $ord = stripos($query, ' ASC', $ob); 594 } 595 if ( stripos($query, ' DESC', $ob) > 0 ) { 596 $ord = stripos($query, ' DESC', $ob); 597 } 598 $str = 'BY '; 599 $str .= implode(', ',$fields); 600 601 $query = substr_replace($query, $str, $ob, ($ord-$ob)); 602 } 603 } 604 } 605 return $query; 606 } 607 608 609 /** 610 * To sort text fields they need to be first cast as varchar 611 * 612 * @since 2.7.1 613 * 614 * @param string $query Query coming in 615 * 616 * @return string Translated Query 617 */ 618 function translate_sort_casting($query) 619 { 620 if ( in_array('translate_limit', $this->translation_changes) ) { 621 return $query; 622 } 623 if ( stripos($query, 'ORDER') > 0 ) { 624 $order_pos = stripos($query, 'ORDER'); 625 if ( stripos($query, 'BY', $order_pos) == ($order_pos + 6)) { 626 $ob = stripos($query, 'BY', $order_pos); 627 if ( stripos($query,' ASC', $ob) > 0 ) { 628 $ord = stripos($query, ' ASC', $ob); 629 } 630 if ( stripos($query,' DESC', $ob) > 0 ) { 631 $ord = stripos($query, ' DESC', $ob); 632 } 633 634 $params = substr($query, ($ob + 3), ($ord - ($ob + 3))); 635 $params = preg_split('/[\s,]+/', $params); 636 $p = array(); 637 foreach ( $params as $value ) { 638 $value = str_replace(',', '', $value); 639 if ( !empty($value) ) { 640 $p[] = $value; 641 } 642 } 643 $str = ''; 644 645 foreach ($p as $v ) { 646 $match = false; 647 foreach( $this->fields_map->read() as $table => $table_fields ) { 648 if ( is_array($table_fields) ) { 649 foreach ( $table_fields as $field => $field_meta) { 650 if ( $field_meta['type'] == 'text' ) { 651 if ( $v == $table . '.' . $field || $v == $field ) { 652 $match = true; 653 } 654 } 655 } 656 } 657 } 658 if ( $match ) { 659 $str .= 'cast(' . $v . ' as varchar(255)), '; 660 } else { 661 $str .= $v . ', '; 662 } 663 } 664 $str = rtrim($str, ', '); 665 $query = substr_replace( $query, $str, ($ob + 3), ($ord - ($ob + 3)) ); 666 } 667 } 668 return $query; 669 } 670 671 /** 672 * Meta key fix. \_% to [_]% 673 * 674 * @since 2.7.1 675 * 676 * @param string $query Query coming in 677 * 678 * @return string Translated Query 679 */ 680 function translate_column_type($query) 681 { 682 if ( stripos($query, "LIKE '\_%'") > 0 ) { 683 $start_pos = stripos($query, "LIKE '\_%'"); 684 $end_pos = $start_pos + 10; 685 $str = "LIKE '[_]%'"; 686 $query = substr_replace($query, $str, $start_pos, ($end_pos - $start_pos)); 687 } 688 return $query; 689 } 690 691 692 /** 693 * Remove group by stmt in certain queries as T-SQL will 694 * want all column names to execute query properly 695 * 696 * FIXES: Column 'wp_posts.post_author' is invalid in the select list because 697 * it is not contained in either an aggregate function or the GROUP BY clause. 698 * 699 * @since 2.7.1 700 * 701 * @param string $query Query coming in 702 * 703 * @return string Translated Query 704 */ 705 function translate_remove_groupby($query) 706 { 707 $query = str_ireplace("GROUP BY {$this->prefix}posts.ID ", ' ', $query); 708 // Fixed query for archives widgets. 709 $query = str_ireplace( 710 'GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC', 711 'GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY month DESC, year DESC', 712 $query 713 ); 714 return $query; 715 } 716 717 718 /** 719 * When INSERTING 0000-00-00 00:00:00 or '' for datetime SQL Server says wtf 720 * because it's null value begins at 1900-01-01...so lets change this to current time. 721 * 722 * @since 2.7.1 723 * 724 * @param string $query Query coming in 725 * 726 * @return string Translated Query 727 */ 728 function translate_insert_nulltime($query) 729 { 730 if ( stripos($query, 'INSERT') === 0 ) { 731 // Lets grab the fields to be inserted into and their position 732 // based on the csv. 733 $first_paren = stripos($query, '(', 11) + 1; 734 $last_paren = $this->get_matching_paren($query, $first_paren); 735 $fields = explode(',',substr($query, $first_paren, ($last_paren - $first_paren))); 736 $date_fields = array(); 737 $date_fields_map = $this->fields_map->by_type('date'); 738 foreach ( $fields as $key => $field ) { 739 $field = trim($field); 740 741 if ( in_array($field, $date_fields_map) ) { 742 $date_fields[] = array('pos' => $key, 'field' => $field); 743 } 744 } 745 // we have date fields to check 746 if ( count($date_fields) > 0 ) { 747 // we need to get the values 748 $values_pos = stripos($query, 'VALUES'); 749 $first_paren = stripos($query, '(', $values_pos); 750 $last_paren = $this->get_matching_paren($query, ($first_paren + 1)); 751 $values = explode(',',substr($query, ($first_paren+1), ($last_paren-($first_paren+1)))); 752 foreach ( $date_fields as $df ) { 753 $v = trim($values[$df['pos']]); 754 $quote = ( stripos($v, "'0000-00-00 00:00:00'") === 0 || $v === "''" ) ? "'" : ''; 755 if ( stripos($v, '0000-00-00 00:00:00') === 0 756 || stripos($v, "'0000-00-00 00:00:00'") === 0 757 || $v === "''" ) { 758 if ( stripos($df['field'], 'gmt') > 0 ) { 759 $v = $quote.gmdate('Y-m-d H:i:s').$quote; 760 } else { 761 $v = $quote.date('Y-m-d H:i:s').$quote; 762 } 763 } 764 $values[$df['pos']] = $v; 765 } 766 $str = implode(',', $values); 767 $query = substr_replace($query, $str, ($first_paren+1), ($last_paren-($first_paren+1))); 768 } 769 } 770 return $query; 771 } 772 773 /** 774 * The data types text and varchar are incompatible in the equal to operator. 775 * TODO: Have a check for the appropriate table of the field to 776 * prevent plugin collision. 777 * 778 * @since 2.7.1 779 * 780 * @param string $query Query coming in 781 * 782 * @return string Translated Query 783 */ 784 function translate_incompat_data_type($query) 785 { 786 // Lets check to make sure this is a SELECT query. 787 if ( stripos($query, 'SELECT') === 0 ) { 788 $operators = array( 789 '=' => 'LIKE', 790 '!=' => 'NOT LIKE', 791 '<>' => 'NOT LIKE' 792 ); 793 794 foreach ( $this->fields_map->read() as $table => $table_fields ) { 795 if ( is_array($table_fields) ) { 796 foreach ( $table_fields as $field => $field_meta ) { 797 if ( $field_meta['type'] == 'text' ) { 798 foreach ( $operators as $oper => $val ) { 799 $query = str_ireplace( 800 $table . '.' . $field . ' ' . $oper, 801 $table . '.' . $field . ' ' . $val, 802 $query 803 ); 804 $query = str_ireplace($field . ' ' . $oper, $field . ' ' . $val, $query); 805 } 806 } 807 } 808 } 809 } 810 } 811 return $query; 812 } 813 814 /** 815 * General create/alter query translations 816 * 817 * @since 2.7.1 818 * 819 * @param string $query Query coming in 820 * 821 * @return string Translated Query 822 */ 823 function translate_create_queries($query) 824 { 825 if ( stripos($query, 'CREATE') !== 0 && stripos($query, 'ALTER') !== 0 ) { 826 return $query; 827 } 828 // deal with alters in a bit 829 if (stripos($query, 'ALTER') === 0) { 830 return $query; 831 } 832 833 // fix enum as it doesn't exist in T-SQL 834 if ( stripos($query, 'enum(') !== false ) { 835 $enums = array_reverse($this->stripos_all($query, 'enum(')); 836 foreach ( $enums as $start_pos ) { 837 $end = $this->get_matching_paren($query, $start_pos + 5); 838 // get values inside enum 839 $values = substr($query, $start_pos + 5, ($end - ($start_pos + 5))); 840 $values = explode(',', $values); 841 $all_int = true; 842 foreach ( $values as $value ) { 843 $val = trim(str_replace("'", '', $value)); 844 if ( !is_numeric($val) || (int) $val != $val ) { 845 $all_int = false; 846 } 847 } 848 // if enum of ints create an appropriate int column otherwise create a varchar 849 if ( $all_int ) { 850 $query = substr_replace($query, 'smallint', $start_pos, ($end + 1) - $start_pos); 851 } else { 852 $query = substr_replace($query, 'varchar(255)', $start_pos, ($end + 1) - $start_pos); 853 } 854 } 855 } 856 857 // remove IF NOT EXISTS as that doesn't exist in T-SQL 858 $query = str_ireplace(' IF NOT EXISTS', '', $query); 859 860 //save array to file_maps 861 $this->fields_map->update_for($query); 862 863 // change auto increment to indentity 864 $start_positions = array_reverse($this->stripos_all($query, 'auto_increment')); 865 if ( stripos($query, 'auto_increment') > 0 ) { 866 foreach ($start_positions as $start_pos) { 867 $query = substr_replace($query, 'IDENTITY(1,1)', $start_pos, 14); 868 } 869 } 870 if ( stripos($query, 'AFTER') > 0 ) { 871 $start_pos = stripos($query, 'AFTER'); 872 $query = substr($query, 0, $start_pos); 873 } 874 // replacement of certain data types and functions 875 $fields = array( 876 'int (', 877 'int(', 878 'index (', 879 'index(', 880 ); 881 882 foreach ( $fields as $field ) { 883 // reverse so that when we make changes it wont effect the next change. 884 $start_positions = array_reverse($this->stripos_all($query, $field)); 885 foreach ( $start_positions as $start_pos ) { 886 $first_paren = stripos($query, '(', $start_pos); 887 $end_pos = $this->get_matching_paren($query, $first_paren + 1) + 1; 888 if ( $field == 'index(' || $field == 'index (' ) { 889 $query = substr_replace($query, '', $start_pos, $end_pos - $start_pos); 890 } else { 891 $query = substr_replace($query, rtrim(rtrim($field,'('), ' '), $start_pos, ($end_pos - $start_pos)); 892 } 893 } 894 } 895 896 $query = str_ireplace("'0000-00-00 00:00:00'", 'getdate()', $query); 897 898 // strip unsigned 899 $query = str_ireplace("unsigned ", '', $query); 900 901 // strip collation, engine type, etc from end of query 902 $pos = stripos($query, '(', stripos($query, 'TABLE ')); 903 $end = $this->get_matching_paren($query, $pos + 1); 904 $query = substr_replace($query, ');', $end); 905 906 $query = str_ireplace("DEFAULT CHARACTER SET utf8", '', $query); 907 $query = str_ireplace(" CHARACTER SET utf8", '', $query); 908 909 // add collation 910 $ac_types = array('tinytext', 'longtext', 'mediumtext', 'varchar'); 911 foreach ( $ac_types as $ac_type ) { 912 $start_positions = array_reverse($this->stripos_all($query, $ac_type)); 913 foreach ( $start_positions as $start_pos ) { 914 if ($ac_type == 'varchar') { 915 $end = $this->get_matching_paren($query, $start_pos + (strlen($ac_type) + 1)); 916 $sub = substr($query, $end + 2, 7); 917 $end_pos = $end + 1; 918 } else { 919 $query = substr_replace($query, 'TEXT', $start_pos, strlen($ac_type)); 920 $sub = substr($query, $start_pos + 5, 7); 921 $end_pos = $start_pos + 4; 922 } 923 if ( $sub !== 'COLLATE' ) { 924 $query = $this->add_collation($query, $end_pos); 925 } 926 } 927 } 928 929 $keys = array(); 930 $table_pos = stripos($query, ' TABLE ') + 6; 931 $table = substr($query, $table_pos, stripos($query, '(', $table_pos) - $table_pos); 932 $table = trim($table); 933 934 $reserved_words = array('public'); 935 // get column names to check for reserved words to encapsulate with [ ] 936 foreach ( $this->fields_map->read() as $table_name => $table_fields ) { 937 if ( $table_name == $table && is_array($table_fields) ) { 938 foreach ( $table_fields as $field => $field_meta ) { 939 if ( in_array($field, $reserved_words) ) { 940 $query = str_ireplace($field, "[{$field}]", $query); 941 } 942 } 943 } 944 } 945 946 // get primary key constraints 947 if ( stripos($query, 'PRIMARY KEY') > 0) { 948 $start_positions = $this->stripos_all($query, 'PRIMARY KEY'); 949 foreach ( $start_positions as $start_pos ) { 950 $start = stripos($query, '(', $start_pos); 951 $end_paren = $this->get_matching_paren($query, $start + 1); 952 $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1))); 953 foreach ( $field as $k => $v ) { 954 if ( stripos($v, '(') !== false ) { 955 $field[$k] = preg_replace('/\(.*\)/', '', $v); 956 } 957 } 958 $keys[] = array('type' => 'PRIMARY KEY', 'pos' => $start_pos, 'field' => $field); 959 } 960 } 961 // get unique key constraints 962 if ( stripos($query, 'UNIQUE KEY') > 0 ) { 963 $start_positions = $this->stripos_all($query, 'UNIQUE KEY'); 964 foreach ($start_positions as $start_pos) { 965 $start = stripos($query, '(', $start_pos); 966 $end_paren = $this->get_matching_paren($query, $start + 1); 967 $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1))); 968 foreach ( $field as $k => $v ) { 969 if ( stripos($v, '(') !== false ) { 970 $field[$k] = preg_replace('/\(.*\)/', '', $v); 971 } 972 } 973 $keys[] = array('type' => 'UNIQUE KEY', 'pos' => $start_pos, 'field' => $field); 974 } 975 } 976 // get key constraints 977 if ( stripos($query, 'KEY') > 0) { 978 $start_positions = $this->stripos_all($query, 'KEY'); 979 foreach ( $start_positions as $start_pos ) { 980 if ( substr($query, $start_pos - 7, 6) !== 'UNIQUE' 981 && substr($query, $start_pos - 8, 7) !== 'PRIMARY' 982 && (substr($query, $start_pos - 1, 1) == ' ' || substr($query, $start_pos - 1, 1) == "\n") ) { 983 $start = stripos($query, '(', $start_pos); 984 $end_paren = $this->get_matching_paren($query, $start + 1); 985 $field = explode(',', substr($query, $start + 1, $end_paren - ($start + 1))); 986 foreach ( $field as $k => $v ) { 987 if ( stripos($v, '(') !== false ) { 988 $field[$k] = preg_replace('/\(.*\)/', '', $v); 989 } 990 } 991 $keys[] = array('type' => 'KEY', 'pos' => $start_pos, 'field' => $field); 992 } 993 } 994 } 995 996 $count = count($keys); 997 $add_primary = false; 998 $key_str = ''; 999 $lowest_start_pos = false; 1000 $unwanted = array( 1001 'slug', 1002 'name', 1003 'term_id', 1004 'taxonomy', 1005 'term_taxonomy_id', 1006 'comment_approved', 1007 'comment_post_ID', 1008 'comment_approved', 1009 'link_visible', 1010 'post_id', 1011 'meta_key', 1012 'post_type', 1013 'post_status', 1014 'post_date', 1015 'ID', 1016 'post_name', 1017 'post_parent', 1018 'user_login', 1019 'user_nicename', 1020 'user_id', 1021 ); 1022 for ( $i = 0; $i < $count; $i++ ) { 1023 if ( $keys[$i]['pos'] < $lowest_start_pos || $lowest_start_pos === false ) { 1024 $lowest_start_pos = $keys[$i]['pos']; 1025 } 1026 if ( $keys[$i]['type'] == 'PRIMARY KEY' ) { 1027 $add_primary = true; 1028 } 1029 switch ( $keys[$i]['type'] ) { 1030 case 'PRIMARY KEY': 1031 $str = "CONSTRAINT [" . $table . "_" . implode('_', $keys[$i]['field']) . "] PRIMARY KEY CLUSTERED (" . implode(',', $keys[$i]['field']) . ") WITH (IGNORE_DUP_KEY = OFF)"; 1032 if (!$this->azure ) { 1033 $str .= " ON [PRIMARY]"; 1034 } 1035 break; 1036 case 'UNIQUE KEY': 1037 $check = true; 1038 foreach ( $keys[$i]['field'] as $field ) { 1039 if ( in_array($field, $unwanted) ) { 1040 $check = false; 1041 } 1042 } 1043 if ( $check ) { 1044 $str = "CONSTRAINT [" . $table . "_" . implode('_', $keys[$i]['field']) . "] UNIQUE NONCLUSTERED (" . implode(',', $keys[$i]['field']) . ")"; 1045 } else { 1046 $str = ''; 1047 } 1048 break; 1049 case 'KEY': 1050 // CREATE NONCLUSTERED INDEX index_name ON table(col1,col2) 1051 $check = true; 1052 $str = ''; 1053 foreach ( $keys[$i]['field'] as $field ) { 1054 if ( in_array($field, $unwanted) ) { 1055 $check = false; 1056 } 1057 } 1058 if ( $check ) { 1059 if ( !is_array($this->following_query) && $this->following_query === false ) { 1060 $this->following_query = array(); 1061 } elseif (!is_array($this->following_query)) { 1062 $this->following_query = array($this->following_query); 1063 } 1064 $this->following_query[] = "CREATE NONCLUSTERED INDEX " . 1065 $table . "_" . implode('_', $keys[$i]['field']) . 1066 " ON ".$table."(".implode(',', $keys[$i]['field']).")"; 1067 } 1068 break; 1069 } 1070 if ( $i !== $count - 1 && $str !== '' ) { 1071 $str .= ','; 1072 } 1073 $key_str .= $str . "\n"; 1074 } 1075 if ( $key_str !== '' ) { 1076 if ( $add_primary && !$this->azure ) { 1077 $query = substr_replace($query, $key_str . ") ON [PRIMARY];", $lowest_start_pos); 1078 } else { 1079 $query = substr_replace($query, $key_str . ");", $lowest_start_pos); 1080 } 1081 } 1082 1083 return $query; 1084 } 1085 1086 /** 1087 * Given a first parenthesis ( ...will find its matching closing paren ) 1088 * 1089 * @since 2.7.1 1090 * 1091 * @param string $str given string 1092 * @param int $start_pos position of where desired starting paren begins+1 1093 * 1094 * @return int position of matching ending parenthesis 1095 */ 1096 function get_matching_paren($str, $start_pos) 1097 { 1098 $count = strlen($str); 1099 $bracket = 1; 1100 for ( $i = $start_pos; $i < $count; $i++ ) { 1101 if ( $str[$i] == '(' ) { 1102 $bracket++; 1103 } elseif ( $str[$i] == ')' ) { 1104 $bracket--; 1105 } 1106 if ( $bracket == 0 ) { 1107 return $i; 1108 } 1109 } 1110 } 1111 1112 /** 1113 * Get the Aliases in a query 1114 * E.G. Field1 AS yyear, Field2 AS mmonth 1115 * will return array with yyear and mmonth 1116 * 1117 * @since 2.7.1 1118 * 1119 * @param string $str a query 1120 * 1121 * @return array array of aliases in a query 1122 */ 1123 function get_as_fields($query) 1124 { 1125 $arr = array(); 1126 $tok = preg_split('/[\s,]+/', $query); 1127 $count = count($tok); 1128 for ( $i = 0; $i < $count; $i++ ) { 1129 if ( strtolower($tok[$i]) === 'as' ) { 1130 $arr[] = $tok[($i + 1)]; 1131 } 1132 } 1133 return $arr; 1134 } 1135 1136 /** 1137 * Fix for SQL Server returning null values with one space. 1138 * Fix for SQL Server returning datetime fields with milliseconds. 1139 * Fix for SQL Server returning integer fields as integer (mysql returns as string) 1140 * 1141 * @since 2.7.1 1142 * 1143 * @param array $result_set result set array of an executed query 1144 * 1145 * @return array result set array with modified fields 1146 */ 1147 function fix_results($result_set) 1148 { 1149 // If empty bail early. 1150 if ( is_null($result_set)) { 1151 return false; 1152 } 1153 if ( is_array($result_set) && empty($result_set) ) { 1154 return array(); 1155 } 1156 $map_fields = $this->fields_map->by_type('date'); 1157 $fields = array_keys(get_object_vars(current($result_set))); 1158 foreach ( $result_set as $key => $result ) { 1159 // Remove milliseconds 1160 foreach ( $map_fields as $date_field ) { 1161 if ( isset($result->$date_field) ) { 1162 // date_format is a PHP5 function. sqlsrv is only PHP5 compat 1163 // the result set for datetime columns is a PHP DateTime object, to extract 1164 // the string we need to use date_format(). 1165 if ( is_object($result->$date_field) ) { 1166 $result_set[$key]->$date_field = date_format($result->$date_field, 'Y-m-d H:i:s'); 1167 } 1168 } 1169 } 1170 // Check for null values being returned as space and change integers to strings (to mimic mysql results) 1171 foreach ( $fields as $field ) { 1172 if ( $field == 'crdate' || $field == 'refdate' ) { 1173 $result_set[$key]->$field = date_format($result->$field, 'Y-m-d H:i:s'); 1174 } 1175 if ( $result->$field === ' ' ) { 1176 $result->$field = ''; 1177 } 1178 if ( is_int($result->$field) ) { 1179 $result->$field = (string) $result->$field; 1180 } 1181 } 1182 } 1183 return $result_set; 1184 } 1185 1186 /** 1187 * Check to see if an INSERT query has multiple VALUES blocks. If so we need create 1188 * seperate queries for each. 1189 * @since 2.7.1 1190 * 1191 * @param string $query Query coming in 1192 * 1193 * @return array array of insert queries 1194 */ 1195 function split_insert_values($query) 1196 { 1197 $arr = array(); 1198 if ( stripos($query, 'INSERT') === 0 ) { 1199 $first = substr($query, 0, (stripos($query, 'VALUES') + 7)); 1200 $values = substr($query, (stripos($query, 'VALUES') + 7)); 1201 $arr = preg_split('/\),\s+\(/', $values); 1202 foreach ( $arr as $k => $v ) { 1203 if ( substr($v, -1) !== ')' ) { 1204 $v = $v . ')'; 1205 } 1206 1207 if ( substr($v, 0, 1) !== '(' ) { 1208 $v = '(' . $v; 1209 } 1210 1211 $arr[$k] = $first . $v; 1212 } 1213 } 1214 if ( count($arr) < 2 ) { 1215 return $query; 1216 } 1217 return $arr; 1218 } 1219 1220 /** 1221 * Check query to make sure translations weren't made to INSERT query values 1222 * If so replace translation with original data. 1223 * E.G. INSERT INTO wp_posts (wp_title) VALUES ('SELECT * FROM wp_posts LIMIT 1'); 1224 * The translations may change the value data to SELECT TOP 1 FROM wp_posts...in this case 1225 * we don't want that to happen. 1226 * 1227 * @since 2.7.1 1228 * 1229 * @param string $query Query coming in 1230 * 1231 * @return string Verified Query 1232 */ 1233 function verify_insert($query) 1234 { 1235 $values_pos = stripos($query, 'VALUES'); 1236 $first_paren = stripos($query, '(', $values_pos); 1237 $last_paren = $this->get_matching_paren($query, $first_paren + 1); 1238 $values = explode(',', substr($query, ($first_paren + 1), ($last_paren-($first_paren + 1)))); 1239 if ( count($this->prepare_args) !== count($values) ) { 1240 return $query; 1241 } 1242 $i = 0; 1243 foreach ( $values as $k => $value ) { 1244 $value = trim($value); 1245 foreach ( $this->prepare_args as $r => $arg ) { 1246 if ( $k == $i && $arg !== $value ) { 1247 if ( $arg !== '' && $arg !== '0000-00-00 00:00:00' ) { 1248 $values[$k] = "'" . $arg . "'"; 1249 } 1250 } 1251 $i++; 1252 } 1253 } 1254 $str = implode(',', $values); 1255 $query = substr_replace($query, $str, ($first_paren + 1), ($last_paren - ($first_paren + 1))); 1256 return $query; 1257 } 1258 1259 /** 1260 * Check query to make sure translations weren't made to UPDATE query values 1261 * If so replace translation with original data. 1262 * E.G. UPDATE wp_posts SET post_title = 'SELECT * FROM wp_posts LIMIT 1' WHERE post_id = 1; 1263 * The translations may change the value data to SELECT TOP 1 FROM wp_posts...in this case 1264 * we don't want that to happen 1265 * 1266 * @since 2.7.1 1267 * 1268 * @param string $query Query coming in 1269 * 1270 * @return string Verified Query 1271 */ 1272 function verify_update($query) 1273 { 1274 $values = array(); 1275 $keys = array_keys($this->update_data); 1276 1277 $start = stripos($query, 'SET') + 3; 1278 $end = strripos($query, 'WHERE'); 1279 $sub = substr($query, $start, $end - $start); 1280 $arr = explode(', ', $sub); 1281 foreach ( $arr as $k => $v ) { 1282 $v = trim($v); 1283 $st = stripos($v, ' ='); 1284 $sv = substr($v, 0, $st); 1285 if ( in_array($sv, $keys) ) { 1286 $sp = substr($v, $st + 4, -1); 1287 $values[] = str_replace("'", "''", $sp); 1288 } 1289 } 1290 $update_data = array_values($this->update_data); 1291 if ( count($update_data) == count($values) ) { 1292 foreach ( $update_data as $key => $val ) { 1293 if ( $update_data[$key] !== $values[$key] ) { 1294 $values[$key] = str_replace("''", "'", $update_data[$key]); 1295 } 1296 } 1297 1298 foreach ( $values as $y => $vt ) { 1299 $values[$y] = $keys[$y] . " = '" . $vt . "'"; 1300 } 1301 $str = implode(', ', $values) . ' '; 1302 $query = substr_replace($query, $str, ($start+1), ($end-($start+1))); 1303 } 1304 return $query; 1305 } 1306 1307 /** 1308 * Add collation for a field definition within a CREATE/ALTER query 1309 * 1310 * @since 2.8 1311 * @param $type 1312 * 1313 * @return string 1314 */ 1315 function add_collation($query, $pos) 1316 { 1317 $query = substr_replace($query, ' COLLATE Latin1_General_BIN', $pos, 0); 1318 return $query; 1319 } 1320 1321 /** 1322 * Describe wrapper 1323 * 1324 * @since 2.8.5 1325 * @param $table 1326 * 1327 * @return string 1328 */ 1329 function describe($table) 1330 { 1331 $sql = "SELECT 1332 c.name AS Field 1333 ,t.name + t.length_string AS Type 1334 ,CASE c.is_nullable WHEN 1 THEN 'YES' ELSE 'NO' END AS [Null] 1335 ,CASE 1336 WHEN EXISTS (SELECT * FROM sys.key_constraints AS kc 1337 INNER JOIN sys.index_columns AS ic ON kc.unique_index_id = ic.index_id AND kc.parent_object_id = ic.object_id 1338 WHERE kc.type = 'PK' AND ic.column_id = c.column_id AND c.object_id = ic.object_id) 1339 THEN 'PRI' 1340 WHEN EXISTS (SELECT * FROM sys.key_constraints AS kc 1341 INNER JOIN sys.index_columns AS ic ON kc.unique_index_id = ic.index_id AND kc.parent_object_id = ic.object_id 1342 WHERE kc.type <> 'PK' AND ic.column_id = c.column_id AND c.object_id = ic.object_id) 1343 THEN 'UNI' 1344 ELSE '' 1345 END AS [Key] 1346 ,ISNULL(( 1347 SELECT TOP(1) 1348 dc.definition 1349 FROM sys.default_constraints AS dc 1350 WHERE dc.parent_column_id = c.column_id AND c.object_id = dc.parent_object_id) 1351 ,'') AS [Default] 1352 ,CASE 1353 WHEN EXISTS ( 1354 SELECT 1355 * 1356 FROM sys.identity_columns AS ic 1357 WHERE ic.column_id = c.column_id AND c.object_id = ic.object_id) 1358 THEN 'auto_increment' 1359 ELSE '' 1360 END AS Extra 1361 FROM sys.columns AS c 1362 CROSS APPLY ( 1363 SELECT 1364 t.name AS n1 1365 ,CASE 1366 -- Types with length 1367 WHEN c.max_length > 0 AND t.name IN ('varchar', 'char', 'varbinary', 'binary') THEN '(' + CAST(c.max_length AS VARCHAR) + ')' 1368 WHEN c.max_length > 0 AND t.name IN ('nvarchar', 'nchar') THEN '(' + CAST(c.max_length/2 AS VARCHAR) + ')' 1369 WHEN c.max_length < 0 AND t.name IN ('nvarchar', 'varchar', 'varbinary') THEN '(max)' 1370 -- Types with precision & scale 1371 WHEN t.name IN ('decimal', 'numeric') THEN '(' + CAST(c.precision AS VARCHAR) + ',' + CAST(c.scale AS VARCHAR) + ')' 1372 -- Types with only precision 1373 WHEN t.name IN ('float') THEN '(' + CAST(c.precision AS VARCHAR) + ')' 1374 -- Types with only scale 1375 WHEN t.name IN ('datetime2', 'time', 'datetimeoffset') THEN '(' + CAST(c.scale AS VARCHAR) + ')' 1376 -- The rest take no arguments 1377 ELSE '' 1378 END AS length_string 1379 ,* 1380 FROM sys.types AS t 1381 WHERE t.system_type_id = c.system_type_id AND t.system_type_id = t.user_type_id 1382 ) AS t 1383 WHERE object_id = OBJECT_ID('{$table}');"; 1384 return $sql; 1385 } 1386 1387 /** 1388 * Get all occurrences(positions) of a string within a string 1389 * 1390 * @since 2.8 1391 * @param $type 1392 * 1393 * @return array 1394 */ 1395 function stripos_all($haystack, $needle, $offset = 0) 1396 { 1397 $arr = array(); 1398 while ( $offset !== false ) { 1399 $pos = stripos($haystack, $needle, $offset); 1400 if ( $pos !== false ) { 1401 $arr[] = $pos; 1402 $pos = $pos + strlen($needle); 1403 } 1404 $offset = $pos; 1405 } 1406 return $arr; 1407 } 1408 } 1409 1410 if ( !function_exists('str_ireplace') ) { 1411 /** 1412 * PHP 4 Compatible str_ireplace function 1413 * found in php.net comments 1414 * 1415 * @since 2.7.1 1416 * 1417 * @param string $search what needs to be replaced 1418 * @param string $replace replacing value 1419 * @param string $subject string to perform replace on 1420 * 1421 * @return string the string with replacements 1422 */ 1423 function str_ireplace($search, $replace, $subject) 1424 { 1425 $token = chr(1); 1426 $haystack = strtolower($subject); 1427 $needle = strtolower($search); 1428 while ( $pos = strpos($haystack, $needle) !== FALSE ) { 1429 $subject = substr_replace($subject, $token, $pos, strlen($search)); 1430 $haystack = substr_replace($haystack, $token, $pos, strlen($search)); 1431 } 1432 return str_replace($token, $replace, $subject); 1433 } 1434 } 1435 1436 if ( !function_exists('stripos') ) { 1437 /** 1438 * PHP 4 Compatible stripos function 1439 * found in php.net comments 1440 * 1441 * @since 2.7.1 1442 * 1443 * @param string $str the string to search in 1444 * @param string $needle what we are looking for 1445 * @param int $offset starting position 1446 * 1447 * @return int position of needle if found. FALSE if not found. 1448 */ 1449 function stripos($str, $needle, $offset = 0) 1450 { 1451 return strpos(strtolower($str), strtolower($needle), $offset); 1452 } 1453 } 1454 1455 if ( !function_exists('strripos') ) { 1456 /** 1457 * PHP 4 Compatible strripos function 1458 * found in php.net comments 1459 * 1460 * @since 2.7.1 1461 * 1462 * @param string $haystack the string to search in 1463 * @param string $needle what we are looking for 1464 * 1465 * @return int position of needle if found. FALSE if not found. 1466 */ 1467 function strripos($haystack, $needle, $offset = 0) 1468 { 1469 if ( !is_string($needle) ) { 1470 $needle = chr(intval($needle)); 1471 } 1472 if ( $offset < 0 ) { 1473 $temp_cut = strrev(substr($haystack, 0, abs($offset))); 1474 } else { 1475 $temp_cut = strrev(substr($haystack, 0, max((strlen($haystack) - $offset ), 0))); 1476 } 1477 if ( stripos($temp_cut, strrev($needle)) === false ) { 1478 return false; 1479 } else { 1480 $found = stripos($temp_cut, strrev($needle)); 1481 } 1482 $pos = ( strlen($haystack) - ($found + $offset + strlen($needle)) ); 1483 return $pos; 1484 } 1485 } -
wp-includes/wp-db/mysql/mysql.php
Property changes on: wp-includes\wp-db\mssql\translations\translations.php ___________________________________________________________________ Added: svn:eol-style + native
1 <?php 2 /** 3 * WordPress DB Class 4 * 5 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)} 6 * 7 * @package WordPress 8 * @subpackage Database 9 * @since 0.71 10 */ 11 12 /** 13 * @since 0.71 14 */ 15 define('EZSQL_VERSION', 'WP1.25'); 16 17 /** 18 * @since 0.71 19 */ 20 define('OBJECT', 'OBJECT', true); 21 22 /** 23 * @since {@internal Version Unknown}} 24 */ 25 define('OBJECT_K', 'OBJECT_K', false); 26 27 /** 28 * @since 0.71 29 */ 30 define('ARRAY_A', 'ARRAY_A', false); 31 32 /** 33 * @since 0.71 34 */ 35 define('ARRAY_N', 'ARRAY_N', false); 36 37 /** 38 * WordPress Database Access Abstraction Object 39 * 40 * It is possible to replace this class with your own 41 * by setting the $wpdb global variable in wp-content/db.php 42 * file with your class. You can name it wpdb also, since 43 * this file will not be included, if the other file is 44 * available. 45 * 46 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class 47 * 48 * @package WordPress 49 * @subpackage Database 50 * @since 0.71 51 * @final 52 */ 53 class wpdb { 54 55 /** 56 * Whether to show SQL/DB errors 57 * 58 * @since 0.71 59 * @access private 60 * @var bool 61 */ 62 var $show_errors = false; 63 64 /** 65 * Whether to suppress errors during the DB bootstrapping. 66 * 67 * @access private 68 * @since {@internal Version Unknown}} 69 * @var bool 70 */ 71 var $suppress_errors = false; 72 73 /** 74 * The last error during query. 75 * 76 * @since {@internal Version Unknown}} 77 * @var string 78 */ 79 var $last_error = ''; 80 81 /** 82 * Amount of queries made 83 * 84 * @since 1.2.0 85 * @access private 86 * @var int 87 */ 88 var $num_queries = 0; 89 90 /** 91 * Saved result of the last query made 92 * 93 * @since 1.2.0 94 * @access private 95 * @var array 96 */ 97 var $last_query; 98 99 /** 100 * Saved info on the table column 101 * 102 * @since 1.2.0 103 * @access private 104 * @var array 105 */ 106 var $col_info; 107 108 /** 109 * Saved queries that were executed 110 * 111 * @since 1.5.0 112 * @access private 113 * @var array 114 */ 115 var $queries; 116 117 /** 118 * WordPress table prefix 119 * 120 * You can set this to have multiple WordPress installations 121 * in a single database. The second reason is for possible 122 * security precautions. 123 * 124 * @since 0.71 125 * @access private 126 * @var string 127 */ 128 var $prefix = ''; 129 130 /** 131 * Whether the database queries are ready to start executing. 132 * 133 * @since 2.5.0 134 * @access private 135 * @var bool 136 */ 137 var $ready = false; 138 139 /** 140 * WordPress Posts table 141 * 142 * @since 1.5.0 143 * @access public 144 * @var string 145 */ 146 var $posts; 147 148 /** 149 * WordPress Users table 150 * 151 * @since 1.5.0 152 * @access public 153 * @var string 154 */ 155 var $users; 156 157 /** 158 * WordPress Categories table 159 * 160 * @since 1.5.0 161 * @access public 162 * @var string 163 */ 164 var $categories; 165 166 /** 167 * WordPress Post to Category table 168 * 169 * @since 1.5.0 170 * @access public 171 * @var string 172 */ 173 var $post2cat; 174 175 /** 176 * WordPress Comments table 177 * 178 * @since 1.5.0 179 * @access public 180 * @var string 181 */ 182 var $comments; 183 184 /** 185 * WordPress Links table 186 * 187 * @since 1.5.0 188 * @access public 189 * @var string 190 */ 191 var $links; 192 193 /** 194 * WordPress Options table 195 * 196 * @since 1.5.0 197 * @access public 198 * @var string 199 */ 200 var $options; 201 202 /** 203 * WordPress Post Metadata table 204 * 205 * @since {@internal Version Unknown}} 206 * @access public 207 * @var string 208 */ 209 var $postmeta; 210 211 /** 212 * WordPress Comment Metadata table 213 * 214 * @since 2.9 215 * @access public 216 * @var string 217 */ 218 var $commentmeta; 219 220 /** 221 * WordPress User Metadata table 222 * 223 * @since 2.3.0 224 * @access public 225 * @var string 226 */ 227 var $usermeta; 228 229 /** 230 * WordPress Terms table 231 * 232 * @since 2.3.0 233 * @access public 234 * @var string 235 */ 236 var $terms; 237 238 /** 239 * WordPress Term Taxonomy table 240 * 241 * @since 2.3.0 242 * @access public 243 * @var string 244 */ 245 var $term_taxonomy; 246 247 /** 248 * WordPress Term Relationships table 249 * 250 * @since 2.3.0 251 * @access public 252 * @var string 253 */ 254 var $term_relationships; 255 256 /** 257 * List of WordPress tables 258 * 259 * @since {@internal Version Unknown}} 260 * @access private 261 * @var array 262 */ 263 var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options', 264 'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta'); 265 266 /** 267 * List of deprecated WordPress tables 268 * 269 * @since 2.9.0 270 * @access private 271 * @var array 272 */ 273 var $old_tables = array('categories', 'post2cat', 'link2cat'); 274 275 276 /** 277 * Format specifiers for DB columns. Columns not listed here default to %s. Initialized in wp-settings.php. 278 * 279 * Keys are colmn names, values are format types: 'ID' => '%d' 280 * 281 * @since 2.8.0 282 * @see wpdb:prepare() 283 * @see wpdb:insert() 284 * @see wpdb:update() 285 * @access public 286 * @war array 287 */ 288 var $field_types = array(); 289 290 /** 291 * Database table columns charset 292 * 293 * @since 2.2.0 294 * @access public 295 * @var string 296 */ 297 var $charset; 298 299 /** 300 * Database table columns collate 301 * 302 * @since 2.2.0 303 * @access public 304 * @var string 305 */ 306 var $collate; 307 308 /** 309 * Whether to use mysql_real_escape_string 310 * 311 * @since 2.8.0 312 * @access public 313 * @var bool 314 */ 315 var $real_escape = false; 316 317 /** 318 * Database Username 319 * 320 * @since 2.9.0 321 * @access private 322 * @var string 323 */ 324 var $dbuser; 325 326 /** 327 * Connects to the database server and selects a database 328 * 329 * PHP4 compatibility layer for calling the PHP5 constructor. 330 * 331 * @uses wpdb::__construct() Passes parameters and returns result 332 * @since 0.71 333 * 334 * @param string $dbuser MySQL database user 335 * @param string $dbpassword MySQL database password 336 * @param string $dbname MySQL database name 337 * @param string $dbhost MySQL database host 338 */ 339 function wpdb($dbuser, $dbpassword, $dbname, $dbhost) { 340 return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); 341 } 342 343 /** 344 * Connects to the database server and selects a database 345 * 346 * PHP5 style constructor for compatibility with PHP5. Does 347 * the actual setting up of the class properties and connection 348 * to the database. 349 * 350 * @since 2.0.8 351 * 352 * @param string $dbuser MySQL database user 353 * @param string $dbpassword MySQL database password 354 * @param string $dbname MySQL database name 355 * @param string $dbhost MySQL database host 356 */ 357 function __construct($dbuser, $dbpassword, $dbname, $dbhost) { 358 register_shutdown_function(array(&$this, "__destruct")); 359 360 if ( defined('WP_DEBUG') and WP_DEBUG == true ) 361 $this->show_errors(); 362 363 if ( defined('DB_CHARSET') ) 364 $this->charset = DB_CHARSET; 365 366 if ( defined('DB_COLLATE') ) 367 $this->collate = DB_COLLATE; 368 369 $this->dbuser = $dbuser; 370 371 $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true); 372 if (!$this->dbh) { 373 $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/" 374 <h1>Error establishing a database connection</h1> 375 <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> 376 <ul> 377 <li>Are you sure you have the correct username and password?</li> 378 <li>Are you sure that you have typed the correct hostname?</li> 379 <li>Are you sure that the database server is running?</li> 380 </ul> 381 <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> 382 "/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail'); 383 return; 384 } 385 386 $this->ready = true; 387 388 if ( $this->has_cap( 'collation' ) ) { 389 if ( !empty($this->charset) ) { 390 if ( function_exists('mysql_set_charset') ) { 391 mysql_set_charset($this->charset, $this->dbh); 392 $this->real_escape = true; 393 } else { 394 $collation_query = "SET NAMES '{$this->charset}'"; 395 if ( !empty($this->collate) ) 396 $collation_query .= " COLLATE '{$this->collate}'"; 397 $this->query($collation_query); 398 } 399 } 400 } 401 402 $this->select($dbname); 403 } 404 405 /** 406 * PHP5 style destructor and will run when database object is destroyed. 407 * 408 * @since 2.0.8 409 * 410 * @return bool Always true 411 */ 412 function __destruct() { 413 return true; 414 } 415 416 /** 417 * Sets the table prefix for the WordPress tables. 418 * 419 * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to 420 * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix. 421 * 422 * @since 2.5.0 423 * 424 * @param string $prefix Alphanumeric name for the new prefix. 425 * @return string|WP_Error Old prefix or WP_Error on error 426 */ 427 function set_prefix($prefix) { 428 429 if ( preg_match('|[^a-z0-9_]|i', $prefix) ) 430 return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/); 431 432 $old_prefix = $this->prefix; 433 $this->prefix = $prefix; 434 435 foreach ( (array) $this->tables as $table ) 436 $this->$table = $this->prefix . $table; 437 438 if ( defined('CUSTOM_USER_TABLE') ) 439 $this->users = CUSTOM_USER_TABLE; 440 441 if ( defined('CUSTOM_USER_META_TABLE') ) 442 $this->usermeta = CUSTOM_USER_META_TABLE; 443 444 return $old_prefix; 445 } 446 447 /** 448 * Selects a database using the current database connection. 449 * 450 * The database name will be changed based on the current database 451 * connection. On failure, the execution will bail and display an DB error. 452 * 453 * @since 0.71 454 * 455 * @param string $db MySQL database name 456 * @return null Always null. 457 */ 458 function select($db) { 459 if (!@mysql_select_db($db, $this->dbh)) { 460 $this->ready = false; 461 $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/' 462 <h1>Can’t select database</h1> 463 <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> 464 <ul> 465 <li>Are you sure it exists?</li> 466 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> 467 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li> 468 </ul> 469 <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, $this->dbuser), 'db_select_fail'); 470 return; 471 } 472 } 473 474 function _weak_escape($string) { 475 return addslashes($string); 476 } 477 478 function _real_escape($string) { 479 if ( $this->dbh && $this->real_escape ) 480 return mysql_real_escape_string( $string, $this->dbh ); 481 else 482 return addslashes( $string ); 483 } 484 485 function _escape($data) { 486 if ( is_array($data) ) { 487 foreach ( (array) $data as $k => $v ) { 488 if ( is_array($v) ) 489 $data[$k] = $this->_escape( $v ); 490 else 491 $data[$k] = $this->_real_escape( $v ); 492 } 493 } else { 494 $data = $this->_real_escape( $data ); 495 } 496 497 return $data; 498 } 499 500 /** 501 * Escapes content for insertion into the database using addslashes(), for security 502 * 503 * @since 0.71 504 * 505 * @param string|array $data 506 * @return string query safe string 507 */ 508 function escape($data) { 509 if ( is_array($data) ) { 510 foreach ( (array) $data as $k => $v ) { 511 if ( is_array($v) ) 512 $data[$k] = $this->escape( $v ); 513 else 514 $data[$k] = $this->_weak_escape( $v ); 515 } 516 } else { 517 $data = $this->_weak_escape( $data ); 518 } 519 520 return $data; 521 } 522 523 /** 524 * Escapes content by reference for insertion into the database, for security 525 * 526 * @since 2.3.0 527 * 528 * @param string $s 529 */ 530 function escape_by_ref(&$string) { 531 $string = $this->_real_escape( $string ); 532 } 533 534 /** 535 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. 536 * 537 * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string). 538 * Does not support sign, padding, alignment, width or precision specifiers. 539 * Does not support argument numbering/swapping. 540 * 541 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. 542 * 543 * Both %d and %s should be left unquoted in the query string. 544 * 545 * <code> 546 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 ) 547 * </code> 548 * 549 * @link http://php.net/sprintf Description of syntax. 550 * @since 2.3.0 551 * 552 * @param string $query Query statement with sprintf()-like placeholders 553 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 554 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}. 555 * @return null|string Sanitized query string 556 */ 557 function prepare($query = null) { // ( $query, *$args ) 558 if ( is_null( $query ) ) 559 return; 560 $args = func_get_args(); 561 array_shift($args); 562 // If args were passed as an array (as in vsprintf), move them up 563 if ( isset($args[0]) && is_array($args[0]) ) 564 $args = $args[0]; 565 $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it 566 $query = str_replace('"%s"', '%s', $query); // doublequote unquoting 567 $query = str_replace('%s', "'%s'", $query); // quote the strings 568 array_walk($args, array(&$this, 'escape_by_ref')); 569 return @vsprintf($query, $args); 570 } 571 572 /** 573 * Print SQL/DB error. 574 * 575 * @since 0.71 576 * @global array $EZSQL_ERROR Stores error information of query and error string 577 * 578 * @param string $str The error to display 579 * @return bool False if the showing of errors is disabled. 580 */ 581 function print_error($str = '') { 582 global $EZSQL_ERROR; 583 584 if (!$str) $str = mysql_error($this->dbh); 585 $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str); 586 587 if ( $this->suppress_errors ) 588 return false; 589 590 if ( $caller = $this->get_caller() ) 591 $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); 592 else 593 $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); 594 595 $log_error = true; 596 if ( ! function_exists('error_log') ) 597 $log_error = false; 598 599 $log_file = @ini_get('error_log'); 600 if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) ) 601 $log_error = false; 602 603 if ( $log_error ) 604 @error_log($error_str, 0); 605 606 // Is error output turned on or not.. 607 if ( !$this->show_errors ) 608 return false; 609 610 $str = htmlspecialchars($str, ENT_QUOTES); 611 $query = htmlspecialchars($this->last_query, ENT_QUOTES); 612 613 // If there is an error then take note of it 614 print "<div id='error'> 615 <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br /> 616 <code>$query</code></p> 617 </div>"; 618 } 619 620 /** 621 * Enables showing of database errors. 622 * 623 * This function should be used only to enable showing of errors. 624 * wpdb::hide_errors() should be used instead for hiding of errors. However, 625 * this function can be used to enable and disable showing of database 626 * errors. 627 * 628 * @since 0.71 629 * 630 * @param bool $show Whether to show or hide errors 631 * @return bool Old value for showing errors. 632 */ 633 function show_errors( $show = true ) { 634 $errors = $this->show_errors; 635 $this->show_errors = $show; 636 return $errors; 637 } 638 639 /** 640 * Disables showing of database errors. 641 * 642 * @since 0.71 643 * 644 * @return bool Whether showing of errors was active or not 645 */ 646 function hide_errors() { 647 $show = $this->show_errors; 648 $this->show_errors = false; 649 return $show; 650 } 651 652 /** 653 * Whether to suppress database errors. 654 * 655 * @param unknown_type $suppress 656 * @return unknown 657 */ 658 function suppress_errors( $suppress = true ) { 659 $errors = $this->suppress_errors; 660 $this->suppress_errors = $suppress; 661 return $errors; 662 } 663 664 /** 665 * Kill cached query results. 666 * 667 * @since 0.71 668 */ 669 function flush() { 670 $this->last_result = array(); 671 $this->col_info = null; 672 $this->last_query = null; 673 } 674 675 /** 676 * Perform a MySQL database query, using current database connection. 677 * 678 * More information can be found on the codex page. 679 * 680 * @since 0.71 681 * 682 * @param string $query 683 * @return int|false Number of rows affected/selected or false on error 684 */ 685 function query($query) { 686 if ( ! $this->ready ) 687 return false; 688 689 // filter the query, if filters are available 690 // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method 691 if ( function_exists('apply_filters') ) 692 $query = apply_filters('query', $query); 693 694 // initialise return 695 $return_val = 0; 696 $this->flush(); 697 698 // Log how the function was called 699 $this->func_call = "\$db->query(\"$query\")"; 700 701 // Keep track of the last query for debug.. 702 $this->last_query = $query; 703 704 // Perform the query via std mysql_query function.. 705 if ( defined('SAVEQUERIES') && SAVEQUERIES ) 706 $this->timer_start(); 707 708 $this->result = @mysql_query($query, $this->dbh); 709 ++$this->num_queries; 710 711 if ( defined('SAVEQUERIES') && SAVEQUERIES ) 712 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); 713 714 // If there is an error then take note of it.. 715 if ( $this->last_error = mysql_error($this->dbh) ) { 716 $this->print_error(); 717 return false; 718 } 719 720 if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) { 721 $this->rows_affected = mysql_affected_rows($this->dbh); 722 // Take note of the insert_id 723 if ( preg_match("/^\\s*(insert|replace) /i",$query) ) { 724 $this->insert_id = mysql_insert_id($this->dbh); 725 } 726 // Return number of rows affected 727 $return_val = $this->rows_affected; 728 } else { 729 $i = 0; 730 while ($i < @mysql_num_fields($this->result)) { 731 $this->col_info[$i] = @mysql_fetch_field($this->result); 732 $i++; 733 } 734 $num_rows = 0; 735 while ( $row = @mysql_fetch_object($this->result) ) { 736 $this->last_result[$num_rows] = $row; 737 $num_rows++; 738 } 739 740 @mysql_free_result($this->result); 741 742 // Log number of rows the query returned 743 $this->num_rows = $num_rows; 744 745 // Return number of rows selected 746 $return_val = $this->num_rows; 747 } 748 749 return $return_val; 750 } 751 752 /** 753 * Insert a row into a table. 754 * 755 * <code> 756 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) 757 * </code> 758 * 759 * @since 2.5.0 760 * @see wpdb::prepare() 761 * 762 * @param string $table table name 763 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 764 * @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. 765 * @return int|false The number of rows inserted, or false on error. 766 */ 767 function insert($table, $data, $format = null) { 768 $formats = $format = (array) $format; 769 $fields = array_keys($data); 770 $formatted_fields = array(); 771 foreach ( $fields as $field ) { 772 if ( !empty($format) ) 773 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 774 elseif ( isset($this->field_types[$field]) ) 775 $form = $this->field_types[$field]; 776 else 777 $form = '%s'; 778 $formatted_fields[] = $form; 779 } 780 $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')"; 781 return $this->query( $this->prepare( $sql, $data) ); 782 } 783 784 785 /** 786 * Update a row in the table 787 * 788 * <code> 789 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) 790 * </code> 791 * 792 * @since 2.5.0 793 * @see wpdb::prepare() 794 * 795 * @param string $table table name 796 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 797 * @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". 798 * @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. 799 * @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. 800 * @return int|false The number of rows updated, or false on error. 801 */ 802 function update($table, $data, $where, $format = null, $where_format = null) { 803 if ( !is_array( $where ) ) 804 return false; 805 806 $formats = $format = (array) $format; 807 $bits = $wheres = array(); 808 foreach ( (array) array_keys($data) as $field ) { 809 if ( !empty($format) ) 810 $form = ( $form = array_shift($formats) ) ? $form : $format[0]; 811 elseif ( isset($this->field_types[$field]) ) 812 $form = $this->field_types[$field]; 813 else 814 $form = '%s'; 815 $bits[] = "`$field` = {$form}"; 816 } 817 818 $where_formats = $where_format = (array) $where_format; 819 foreach ( (array) array_keys($where) as $field ) { 820 if ( !empty($where_format) ) 821 $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0]; 822 elseif ( isset($this->field_types[$field]) ) 823 $form = $this->field_types[$field]; 824 else 825 $form = '%s'; 826 $wheres[] = "`$field` = {$form}"; 827 } 828 829 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ); 830 return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) ); 831 } 832 833 /** 834 * Retrieve one variable from the database. 835 * 836 * Executes a SQL query and returns the value from the SQL result. 837 * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified. 838 * If $query is null, this function returns the value in the specified column and row from the previous SQL result. 839 * 840 * @since 0.71 841 * 842 * @param string|null $query SQL query. If null, use the result from the previous query. 843 * @param int $x (optional) Column of value to return. Indexed from 0. 844 * @param int $y (optional) Row of value to return. Indexed from 0. 845 * @return string Database query result 846 */ 847 function get_var($query=null, $x = 0, $y = 0) { 848 $this->func_call = "\$db->get_var(\"$query\",$x,$y)"; 849 if ( $query ) 850 $this->query($query); 851 852 // Extract var out of cached results based x,y vals 853 if ( !empty( $this->last_result[$y] ) ) { 854 $values = array_values(get_object_vars($this->last_result[$y])); 855 } 856 857 // If there is a value return it else return null 858 return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null; 859 } 860 861 /** 862 * Retrieve one row from the database. 863 * 864 * Executes a SQL query and returns the row from the SQL result. 865 * 866 * @since 0.71 867 * 868 * @param string|null $query SQL query. 869 * @param string $output (optional) one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively. 870 * @param int $y (optional) Row to return. Indexed from 0. 871 * @return mixed Database query result in format specifed by $output 872 */ 873 function get_row($query = null, $output = OBJECT, $y = 0) { 874 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; 875 if ( $query ) 876 $this->query($query); 877 else 878 return null; 879 880 if ( !isset($this->last_result[$y]) ) 881 return null; 882 883 if ( $output == OBJECT ) { 884 return $this->last_result[$y] ? $this->last_result[$y] : null; 885 } elseif ( $output == ARRAY_A ) { 886 return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null; 887 } elseif ( $output == ARRAY_N ) { 888 return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null; 889 } else { 890 $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*/); 891 } 892 } 893 894 /** 895 * Retrieve one column from the database. 896 * 897 * Executes a SQL query and returns the column from the SQL result. 898 * If the SQL result contains more than one column, this function returns the column specified. 899 * If $query is null, this function returns the specified column from the previous SQL result. 900 * 901 * @since 0.71 902 * 903 * @param string|null $query SQL query. If null, use the result from the previous query. 904 * @param int $x Column to return. Indexed from 0. 905 * @return array Database query result. Array indexed from 0 by SQL result row number. 906 */ 907 function get_col($query = null , $x = 0) { 908 if ( $query ) 909 $this->query($query); 910 911 $new_array = array(); 912 // Extract the column values 913 for ( $i=0; $i < count($this->last_result); $i++ ) { 914 $new_array[$i] = $this->get_var(null, $x, $i); 915 } 916 return $new_array; 917 } 918 919 /** 920 * Retrieve an entire SQL result set from the database (i.e., many rows) 921 * 922 * Executes a SQL query and returns the entire SQL result. 923 * 924 * @since 0.71 925 * 926 * @param string $query SQL query. 927 * @param string $output (optional) ane of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded. 928 * @return mixed Database query results 929 */ 930 function get_results($query = null, $output = OBJECT) { 931 $this->func_call = "\$db->get_results(\"$query\", $output)"; 932 933 if ( $query ) 934 $this->query($query); 935 else 936 return null; 937 938 if ( $output == OBJECT ) { 939 // Return an integer-keyed array of row objects 940 return $this->last_result; 941 } elseif ( $output == OBJECT_K ) { 942 // Return an array of row objects with keys from column 1 943 // (Duplicates are discarded) 944 foreach ( $this->last_result as $row ) { 945 $key = array_shift( get_object_vars( $row ) ); 946 if ( !isset( $new_array[ $key ] ) ) 947 $new_array[ $key ] = $row; 948 } 949 return $new_array; 950 } elseif ( $output == ARRAY_A || $output == ARRAY_N ) { 951 // Return an integer-keyed array of... 952 if ( $this->last_result ) { 953 $i = 0; 954 foreach( (array) $this->last_result as $row ) { 955 if ( $output == ARRAY_N ) { 956 // ...integer-keyed row arrays 957 $new_array[$i] = array_values( get_object_vars( $row ) ); 958 } else { 959 // ...column name-keyed row arrays 960 $new_array[$i] = get_object_vars( $row ); 961 } 962 ++$i; 963 } 964 return $new_array; 965 } 966 } 967 } 968 969 /** 970 * Retrieve column metadata from the last query. 971 * 972 * @since 0.71 973 * 974 * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill 975 * @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 976 * @return mixed Column Results 977 */ 978 function get_col_info($info_type = 'name', $col_offset = -1) { 979 if ( $this->col_info ) { 980 if ( $col_offset == -1 ) { 981 $i = 0; 982 foreach( (array) $this->col_info as $col ) { 983 $new_array[$i] = $col->{$info_type}; 984 $i++; 985 } 986 return $new_array; 987 } else { 988 return $this->col_info[$col_offset]->{$info_type}; 989 } 990 } 991 } 992 993 /** 994 * Starts the timer, for debugging purposes. 995 * 996 * @since 1.5.0 997 * 998 * @return true 999 */ 1000 function timer_start() { 1001 $mtime = microtime(); 1002 $mtime = explode(' ', $mtime); 1003 $this->time_start = $mtime[1] + $mtime[0]; 1004 return true; 1005 } 1006 1007 /** 1008 * Stops the debugging timer. 1009 * 1010 * @since 1.5.0 1011 * 1012 * @return int Total time spent on the query, in milliseconds 1013 */ 1014 function timer_stop() { 1015 $mtime = microtime(); 1016 $mtime = explode(' ', $mtime); 1017 $time_end = $mtime[1] + $mtime[0]; 1018 $time_total = $time_end - $this->time_start; 1019 return $time_total; 1020 } 1021 1022 /** 1023 * Wraps errors in a nice header and footer and dies. 1024 * 1025 * Will not die if wpdb::$show_errors is true 1026 * 1027 * @since 1.5.0 1028 * 1029 * @param string $message The Error message 1030 * @param string $error_code (optional) A Computer readable string to identify the error. 1031 * @return false|void 1032 */ 1033 function bail($message, $error_code = '500') { 1034 if ( !$this->show_errors ) { 1035 if ( class_exists('WP_Error') ) 1036 $this->error = new WP_Error($error_code, $message); 1037 else 1038 $this->error = $message; 1039 return false; 1040 } 1041 wp_die($message); 1042 } 1043 1044 /** 1045 * Whether or not MySQL database is at least the required minimum version. 1046 * 1047 * @since 2.5.0 1048 * @uses $wp_version 1049 * 1050 * @return WP_Error 1051 */ 1052 function check_database_version() 1053 { 1054 global $wp_version; 1055 // Make sure the server has MySQL 4.0 1056 if ( version_compare($this->db_version(), '4.0.0', '<') ) 1057 return new WP_Error('database_version',sprintf(__('<strong>ERROR</strong>: WordPress %s requires MySQL 4.0.0 or higher'), $wp_version)); 1058 } 1059 1060 /** 1061 * Whether of not the database supports collation. 1062 * 1063 * Called when WordPress is generating the table scheme. 1064 * 1065 * @since 2.5.0 1066 * 1067 * @return bool True if collation is supported, false if version does not 1068 */ 1069 function supports_collation() { 1070 return $this->has_cap( 'collation' ); 1071 } 1072 1073 /** 1074 * Generic function to determine if a database supports a particular feature 1075 * @param string $db_cap the feature 1076 * @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. 1077 * @return bool 1078 */ 1079 function has_cap( $db_cap ) { 1080 $version = $this->db_version(); 1081 1082 switch ( strtolower( $db_cap ) ) : 1083 case 'collation' : // @since 2.5.0 1084 case 'group_concat' : // @since 2.7 1085 case 'subqueries' : // @since 2.7 1086 return version_compare($version, '4.1', '>='); 1087 break; 1088 endswitch; 1089 1090 return false; 1091 } 1092 1093 /** 1094 * Retrieve the name of the function that called wpdb. 1095 * 1096 * Requires PHP 4.3 and searches up the list of functions until it reaches 1097 * the one that would most logically had called this method. 1098 * 1099 * @since 2.5.0 1100 * 1101 * @return string The name of the calling function 1102 */ 1103 function get_caller() { 1104 // requires PHP 4.3+ 1105 if ( !is_callable('debug_backtrace') ) 1106 return ''; 1107 1108 $bt = debug_backtrace(); 1109 $caller = array(); 1110 1111 $bt = array_reverse( $bt ); 1112 foreach ( (array) $bt as $call ) { 1113 if ( @$call['class'] == __CLASS__ ) 1114 continue; 1115 $function = $call['function']; 1116 if ( isset( $call['class'] ) ) 1117 $function = $call['class'] . "->$function"; 1118 $caller[] = $function; 1119 } 1120 $caller = join( ', ', $caller ); 1121 1122 return $caller; 1123 } 1124 1125 /** 1126 * The database version number 1127 * @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. 1128 * @return false|string false on failure, version number on success 1129 */ 1130 function db_version() { 1131 return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh )); 1132 } 1133 } 1134 -
wp-includes/wp-db/mysql/translations/translations.php
Property changes on: wp-includes\wp-db\mysql\mysql.php ___________________________________________________________________ Added: svn:eol-style + native
1 <?php 2 // Necessary SQL Dialect Translations 3 class Translations 4 { 5 // No Translation Necessary 6 function translate($query) 7 { 8 return $query; 9 } 10 } -
wp-includes/wp-db/sqlsrv/sqlsrv.php
Property changes on: wp-includes\wp-db\mysql\translations\translations.php ___________________________________________________________________ Added: svn:eol-style + native
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