X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/9cd344f9b14dd8e0743c1417fdb379b1431c3988..a7cd4c052013b423c6301153f68c7fdbaa2a447b:/wp-includes/wp-db.php diff --git a/wp-includes/wp-db.php b/wp-includes/wp-db.php index bc634382..1656df7b 100644 --- a/wp-includes/wp-db.php +++ b/wp-includes/wp-db.php @@ -12,48 +12,50 @@ /** * @since 0.71 */ -define('EZSQL_VERSION', 'WP1.25'); +define( 'EZSQL_VERSION', 'WP1.25' ); /** * @since 0.71 */ -define('OBJECT', 'OBJECT', true); +define( 'OBJECT', 'OBJECT' ); +define( 'object', 'OBJECT' ); // Back compat. /** - * @since {@internal Version Unknown}} + * @since 2.5.0 */ -define('OBJECT_K', 'OBJECT_K', false); +define( 'OBJECT_K', 'OBJECT_K' ); /** * @since 0.71 */ -define('ARRAY_A', 'ARRAY_A', false); +define( 'ARRAY_A', 'ARRAY_A' ); /** * @since 0.71 */ -define('ARRAY_N', 'ARRAY_N', false); +define( 'ARRAY_N', 'ARRAY_N' ); /** * WordPress Database Access Abstraction Object * * It is possible to replace this class with your own * by setting the $wpdb global variable in wp-content/db.php - * file with your class. You can name it wpdb also, since - * this file will not be included, if the other file is - * available. + * file to your class. The wpdb class will still be included, + * so you can extend it or simply use your own. * * @link http://codex.wordpress.org/Function_Reference/wpdb_Class * * @package WordPress * @subpackage Database * @since 0.71 - * @final */ class wpdb { /** - * Whether to show SQL/DB errors + * Whether to show SQL/DB errors. + * + * Default behavior is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY + * evaluated to true. * * @since 0.71 * @access private @@ -65,7 +67,7 @@ class wpdb { * Whether to suppress errors during the DB bootstrapping. * * @access private - * @since {@internal Version Unknown}} + * @since 2.5.0 * @var bool */ var $suppress_errors = false; @@ -73,10 +75,10 @@ class wpdb { /** * The last error during query. * - * @since {@internal Version Unknown}} + * @since 2.5.0 * @var string */ - var $last_error = ''; + public $last_error = ''; /** * Amount of queries made @@ -88,22 +90,67 @@ class wpdb { var $num_queries = 0; /** - * Saved result of the last query made + * Count of rows returned by previous query * - * @since 1.2.0 + * @since 0.71 + * @access private + * @var int + */ + var $num_rows = 0; + + /** + * Count of affected rows by previous query + * + * @since 0.71 + * @access private + * @var int + */ + var $rows_affected = 0; + + /** + * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT). + * + * @since 0.71 + * @access public + * @var int + */ + var $insert_id = 0; + + /** + * Last query made + * + * @since 0.71 * @access private * @var array */ var $last_query; /** - * Saved info on the table column + * Results of the last query made * - * @since 1.2.0 + * @since 0.71 * @access private + * @var array|null + */ + var $last_result; + + /** + * MySQL result, which is either a resource or boolean. + * + * @since 0.71 + * @access protected + * @var mixed + */ + protected $result; + + /** + * Saved info on the table column + * + * @since 0.71 + * @access protected * @var array */ - var $col_info; + protected $col_info; /** * Saved queries that were executed @@ -114,6 +161,16 @@ class wpdb { */ var $queries; + /** + * The number of times to retry reconnecting before dying. + * + * @since 3.9.0 + * @access protected + * @see wpdb::check_connection() + * @var int + */ + protected $reconnect_retries = 5; + /** * WordPress table prefix * @@ -121,65 +178,109 @@ class wpdb { * in a single database. The second reason is for possible * security precautions. * - * @since 0.71 + * @since 2.5.0 * @access private * @var string */ var $prefix = ''; + /** + * WordPress base table prefix. + * + * @since 3.0.0 + * @access public + * @var string + */ + public $base_prefix; + /** * Whether the database queries are ready to start executing. * - * @since 2.5.0 + * @since 2.3.2 * @access private * @var bool */ var $ready = false; /** - * WordPress Posts table + * {@internal Missing Description}} * - * @since 1.5.0 + * @since 3.0.0 * @access public - * @var string + * @var int */ - var $posts; + public $blogid = 0; /** - * WordPress Users table + * {@internal Missing Description}} * - * @since 1.5.0 + * @since 3.0.0 * @access public - * @var string + * @var int */ - var $users; + public $siteid = 0; /** - * WordPress Categories table + * List of WordPress per-blog tables * - * @since 1.5.0 - * @access public - * @var string + * @since 2.5.0 + * @access private + * @see wpdb::tables() + * @var array */ - var $categories; + var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta', + 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta' ); /** - * WordPress Post to Category table + * List of deprecated WordPress tables + * + * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539 + * + * @since 2.9.0 + * @access private + * @see wpdb::tables() + * @var array + */ + var $old_tables = array( 'categories', 'post2cat', 'link2cat' ); + + /** + * List of WordPress global tables + * + * @since 3.0.0 + * @access private + * @see wpdb::tables() + * @var array + */ + var $global_tables = array( 'users', 'usermeta' ); + + /** + * List of Multisite global tables + * + * @since 3.0.0 + * @access private + * @see wpdb::tables() + * @var array + */ + var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta', + 'sitecategories', 'registration_log', 'blog_versions' ); + + /** + * WordPress Comments table * * @since 1.5.0 * @access public * @var string */ - var $post2cat; + public $comments; /** - * WordPress Comments table + * WordPress Comment Metadata table * - * @since 1.5.0 + * @since 2.9.0 * @access public * @var string */ - var $comments; + public $commentmeta; /** * WordPress Links table @@ -188,7 +289,7 @@ class wpdb { * @access public * @var string */ - var $links; + public $links; /** * WordPress Options table @@ -197,43 +298,43 @@ class wpdb { * @access public * @var string */ - var $options; + public $options; /** * WordPress Post Metadata table * - * @since {@internal Version Unknown}} + * @since 1.5.0 * @access public * @var string */ - var $postmeta; + public $postmeta; /** - * WordPress Comment Metadata table + * WordPress Posts table * - * @since 2.9 + * @since 1.5.0 * @access public * @var string */ - var $commentmeta; + public $posts; /** - * WordPress User Metadata table + * WordPress Terms table * * @since 2.3.0 * @access public * @var string */ - var $usermeta; + public $terms; /** - * WordPress Terms table + * WordPress Term Relationships table * * @since 2.3.0 * @access public * @var string */ - var $terms; + public $term_relationships; /** * WordPress Term Taxonomy table @@ -242,50 +343,108 @@ class wpdb { * @access public * @var string */ - var $term_taxonomy; + public $term_taxonomy; + + /* + * Global and Multisite tables + */ /** - * WordPress Term Relationships table + * WordPress User Metadata table * * @since 2.3.0 * @access public * @var string */ - var $term_relationships; + public $usermeta; /** - * List of WordPress tables + * WordPress Users table * - * @since {@internal Version Unknown}} - * @access private - * @var array + * @since 1.5.0 + * @access public + * @var string */ - var $tables = array('users', 'usermeta', 'posts', 'categories', 'post2cat', 'comments', 'links', 'link2cat', 'options', - 'postmeta', 'terms', 'term_taxonomy', 'term_relationships', 'commentmeta'); + public $users; /** - * List of deprecated WordPress tables + * Multisite Blogs table * - * @since 2.9.0 - * @access private - * @var array + * @since 3.0.0 + * @access public + * @var string + */ + public $blogs; + + /** + * Multisite Blog Versions table + * + * @since 3.0.0 + * @access public + * @var string */ - var $old_tables = array('categories', 'post2cat', 'link2cat'); + public $blog_versions; + /** + * Multisite Registration Log table + * + * @since 3.0.0 + * @access public + * @var string + */ + public $registration_log; /** - * Format specifiers for DB columns. Columns not listed here default to %s. Initialized in wp-settings.php. + * Multisite Signups table * - * Keys are colmn names, values are format types: 'ID' => '%d' + * @since 3.0.0 + * @access public + * @var string + */ + public $signups; + + /** + * Multisite Sites table + * + * @since 3.0.0 + * @access public + * @var string + */ + public $site; + + /** + * Multisite Sitewide Terms table + * + * @since 3.0.0 + * @access public + * @var string + */ + public $sitecategories; + + /** + * Multisite Site Metadata table + * + * @since 3.0.0 + * @access public + * @var string + */ + public $sitemeta; + + /** + * Format specifiers for DB columns. Columns not listed here default to %s. Initialized during WP load. + * + * Keys are column names, values are format types: 'ID' => '%d' * * @since 2.8.0 - * @see wpdb:prepare() - * @see wpdb:insert() - * @see wpdb:update() + * @see wpdb::prepare() + * @see wpdb::insert() + * @see wpdb::update() + * @see wpdb::delete() + * @see wp_set_wpdb_vars() * @access public - * @war array + * @var array */ - var $field_types = array(); + public $field_types = array(); /** * Database table columns charset @@ -294,7 +453,7 @@ class wpdb { * @access public * @var string */ - var $charset; + public $charset; /** * Database table columns collate @@ -303,42 +462,103 @@ class wpdb { * @access public * @var string */ - var $collate; + public $collate; /** - * Whether to use mysql_real_escape_string + * Database Username * - * @since 2.8.0 - * @access public - * @var bool + * @since 2.9.0 + * @access protected + * @var string */ - var $real_escape = false; + protected $dbuser; /** - * Database Username + * Database Password * - * @since 2.9.0 - * @access private + * @since 3.1.0 + * @access protected * @var string */ - var $dbuser; + protected $dbpassword; /** - * Connects to the database server and selects a database + * Database Name + * + * @since 3.1.0 + * @access protected + * @var string + */ + protected $dbname; + + /** + * Database Host * - * PHP4 compatibility layer for calling the PHP5 constructor. + * @since 3.1.0 + * @access protected + * @var string + */ + protected $dbhost; + + /** + * Database Handle * - * @uses wpdb::__construct() Passes parameters and returns result * @since 0.71 + * @access protected + * @var string + */ + protected $dbh; + + /** + * A textual description of the last query/get_row/get_var call * - * @param string $dbuser MySQL database user - * @param string $dbpassword MySQL database password - * @param string $dbname MySQL database name - * @param string $dbhost MySQL database host + * @since 3.0.0 + * @access public + * @var string */ - function wpdb($dbuser, $dbpassword, $dbname, $dbhost) { - return $this->__construct($dbuser, $dbpassword, $dbname, $dbhost); - } + public $func_call; + + /** + * Whether MySQL is used as the database engine. + * + * Set in WPDB::db_connect() to true, by default. This is used when checking + * against the required MySQL version for WordPress. Normally, a replacement + * database drop-in (db.php) will skip these checks, but setting this to true + * will force the checks to occur. + * + * @since 3.3.0 + * @access public + * @var bool + */ + public $is_mysql = null; + + /** + * A list of incompatible SQL modes. + * + * @since 3.9.0 + * @access protected + * @var array + */ + protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', + 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' ); + + /** + * Whether to use mysqli over mysql. + * + * @since 3.9.0 + * @access private + * @var bool + */ + private $use_mysqli = false; + + /** + * Whether we've managed to successfully connect at some point + * + * @since 3.9.0 + * @access private + * @var bool + */ + private $has_connected = false; /** * Connects to the database server and selects a database @@ -347,6 +567,7 @@ class wpdb { * the actual setting up of the class properties and connection * to the database. * + * @link https://core.trac.wordpress.org/ticket/3354 * @since 2.0.8 * * @param string $dbuser MySQL database user @@ -354,94 +575,390 @@ class wpdb { * @param string $dbname MySQL database name * @param string $dbhost MySQL database host */ - function __construct($dbuser, $dbpassword, $dbname, $dbhost) { - register_shutdown_function(array(&$this, "__destruct")); + public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { + register_shutdown_function( array( $this, '__destruct' ) ); - if ( WP_DEBUG ) + if ( WP_DEBUG && WP_DEBUG_DISPLAY ) $this->show_errors(); - if ( defined('DB_CHARSET') ) - $this->charset = DB_CHARSET; + /* Use ext/mysqli if it exists and: + * - WP_USE_EXT_MYSQL is defined as false, or + * - We are a development version of WordPress, or + * - We are running PHP 5.5 or greater, or + * - ext/mysql is not loaded. + */ + if ( function_exists( 'mysqli_connect' ) ) { + if ( defined( 'WP_USE_EXT_MYSQL' ) ) { + $this->use_mysqli = ! WP_USE_EXT_MYSQL; + } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) { + $this->use_mysqli = true; + } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) { + $this->use_mysqli = true; + } + } - if ( defined('DB_COLLATE') ) - $this->collate = DB_COLLATE; + $this->init_charset(); $this->dbuser = $dbuser; + $this->dbpassword = $dbpassword; + $this->dbname = $dbname; + $this->dbhost = $dbhost; - $this->dbh = @mysql_connect($dbhost, $dbuser, $dbpassword, true); - if (!$this->dbh) { - $this->bail(sprintf(/*WP_I18N_DB_CONN_ERROR*/" -
This either means that the username and password information in your wp-config.php
file is incorrect or we can't contact the database server at %s
. This could mean your host's database server is down.
If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums.
-"/*/WP_I18N_DB_CONN_ERROR*/, $dbhost), 'db_connect_fail'); + // wp-config.php creation will manually connect when ready. + if ( defined( 'WP_SETUP_CONFIG' ) ) { return; } - $this->ready = true; + $this->db_connect(); + } - if ( $this->has_cap( 'collation' ) && !empty($this->charset) ) { - if ( function_exists('mysql_set_charset') ) { - mysql_set_charset($this->charset, $this->dbh); - $this->real_escape = true; + /** + * PHP5 style destructor and will run when database object is destroyed. + * + * @see wpdb::__construct() + * @since 2.0.8 + * @return bool true + */ + public function __destruct() { + return true; + } + + /** + * PHP5 style magic getter, used to lazy-load expensive data. + * + * @since 3.5.0 + * + * @param string $name The private member to get, and optionally process + * @return mixed The private member + */ + public function __get( $name ) { + if ( 'col_info' === $name ) + $this->load_col_info(); + + return $this->$name; + } + + /** + * Magic function, for backwards compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to set + * @param mixed $value The value to set + */ + public function __set( $name, $value ) { + $this->$name = $value; + } + + /** + * Magic function, for backwards compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to check + * + * @return bool If the member is set or not + */ + public function __isset( $name ) { + return isset( $this->$name ); + } + + /** + * Magic function, for backwards compatibility. + * + * @since 3.5.0 + * + * @param string $name The private member to unset + */ + public function __unset( $name ) { + unset( $this->$name ); + } + + /** + * Set $this->charset and $this->collate + * + * @since 3.1.0 + */ + public function init_charset() { + if ( function_exists('is_multisite') && is_multisite() ) { + $this->charset = 'utf8'; + if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) + $this->collate = DB_COLLATE; + else + $this->collate = 'utf8_general_ci'; + } elseif ( defined( 'DB_COLLATE' ) ) { + $this->collate = DB_COLLATE; + } + + if ( defined( 'DB_CHARSET' ) ) + $this->charset = DB_CHARSET; + } + + /** + * Sets the connection's character set. + * + * @since 3.1.0 + * + * @param resource $dbh The resource given by mysql_connect + * @param string $charset Optional. The character set. Default null. + * @param string $collate Optional. The collation. Default null. + */ + public function set_charset( $dbh, $charset = null, $collate = null ) { + if ( ! isset( $charset ) ) + $charset = $this->charset; + if ( ! isset( $collate ) ) + $collate = $this->collate; + if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { + if ( $this->use_mysqli ) { + if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { + mysqli_set_charset( $dbh, $charset ); + } else { + $query = $this->prepare( 'SET NAMES %s', $charset ); + if ( ! empty( $collate ) ) + $query .= $this->prepare( ' COLLATE %s', $collate ); + mysqli_query( $query, $dbh ); + } } else { - $collation_query = "SET NAMES '{$this->charset}'"; - if ( !empty($this->collate) ) - $collation_query .= " COLLATE '{$this->collate}'"; - $this->query($collation_query); + if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { + mysql_set_charset( $charset, $dbh ); + } else { + $query = $this->prepare( 'SET NAMES %s', $charset ); + if ( ! empty( $collate ) ) + $query .= $this->prepare( ' COLLATE %s', $collate ); + mysql_query( $query, $dbh ); + } } } - - $this->select($dbname); } /** - * PHP5 style destructor and will run when database object is destroyed. + * Change the current SQL mode, and ensure its WordPress compatibility. * - * @since 2.0.8 + * If no modes are passed, it will ensure the current MySQL server + * modes are compatible. * - * @return bool Always true + * @since 3.9.0 + * + * @param array $modes Optional. A list of SQL modes to set. */ - function __destruct() { - return true; + public function set_sql_mode( $modes = array() ) { + if ( empty( $modes ) ) { + if ( $this->use_mysqli ) { + $res = mysqli_query( $this->dbh, 'SELECT @@SESSION.sql_mode' ); + } else { + $res = mysql_query( 'SELECT @@SESSION.sql_mode', $this->dbh ); + } + + if ( empty( $res ) ) { + return; + } + + if ( $this->use_mysqli ) { + $modes_array = mysqli_fetch_array( $res ); + if ( empty( $modes_array[0] ) ) { + return; + } + $modes_str = $modes_array[0]; + } else { + $modes_str = mysql_result( $res, 0 ); + } + + if ( empty( $modes_str ) ) { + return; + } + + $modes = explode( ',', $modes_str ); + } + + $modes = array_change_key_case( $modes, CASE_UPPER ); + + /** + * Filter the list of incompatible SQL modes to exclude. + * + * @since 3.9.0 + * + * @param array $incompatible_modes An array of incompatible modes. + */ + $incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes ); + + foreach( $modes as $i => $mode ) { + if ( in_array( $mode, $incompatible_modes ) ) { + unset( $modes[ $i ] ); + } + } + + $modes_str = implode( ',', $modes ); + + if ( $this->use_mysqli ) { + mysqli_query( $this->dbh, "SET SESSION sql_mode='$modes_str'" ); + } else { + mysql_query( "SET SESSION sql_mode='$modes_str'", $this->dbh ); + } } /** * Sets the table prefix for the WordPress tables. * - * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to - * override the WordPress users and usersmeta tables that would otherwise be determined by the $prefix. - * * @since 2.5.0 * * @param string $prefix Alphanumeric name for the new prefix. + * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not. * @return string|WP_Error Old prefix or WP_Error on error */ - function set_prefix($prefix) { + public function set_prefix( $prefix, $set_table_names = true ) { + + if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) + return new WP_Error('invalid_db_prefix', 'Invalid database prefix' ); + + $old_prefix = is_multisite() ? '' : $prefix; + + if ( isset( $this->base_prefix ) ) + $old_prefix = $this->base_prefix; - if ( preg_match('|[^a-z0-9_]|i', $prefix) ) - return new WP_Error('invalid_db_prefix', /*WP_I18N_DB_BAD_PREFIX*/'Invalid database prefix'/*/WP_I18N_DB_BAD_PREFIX*/); + $this->base_prefix = $prefix; - $old_prefix = $this->prefix; - $this->prefix = $prefix; + if ( $set_table_names ) { + foreach ( $this->tables( 'global' ) as $table => $prefixed_table ) + $this->$table = $prefixed_table; - foreach ( (array) $this->tables as $table ) - $this->$table = $this->prefix . $table; + if ( is_multisite() && empty( $this->blogid ) ) + return $old_prefix; - if ( defined('CUSTOM_USER_TABLE') ) - $this->users = CUSTOM_USER_TABLE; + $this->prefix = $this->get_blog_prefix(); - if ( defined('CUSTOM_USER_META_TABLE') ) - $this->usermeta = CUSTOM_USER_META_TABLE; + foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) + $this->$table = $prefixed_table; + foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) + $this->$table = $prefixed_table; + } return $old_prefix; } + /** + * Sets blog id. + * + * @since 3.0.0 + * @access public + * @param int $blog_id + * @param int $site_id Optional. + * @return int previous blog id + */ + public function set_blog_id( $blog_id, $site_id = 0 ) { + if ( ! empty( $site_id ) ) + $this->siteid = $site_id; + + $old_blog_id = $this->blogid; + $this->blogid = $blog_id; + + $this->prefix = $this->get_blog_prefix(); + + foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) + $this->$table = $prefixed_table; + + foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) + $this->$table = $prefixed_table; + + return $old_blog_id; + } + + /** + * Gets blog prefix. + * + * @since 3.0.0 + * @param int $blog_id Optional. + * @return string Blog prefix. + */ + public function get_blog_prefix( $blog_id = null ) { + if ( is_multisite() ) { + if ( null === $blog_id ) + $blog_id = $this->blogid; + $blog_id = (int) $blog_id; + if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) + return $this->base_prefix; + else + return $this->base_prefix . $blog_id . '_'; + } else { + return $this->base_prefix; + } + } + + /** + * Returns an array of WordPress tables. + * + * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to + * override the WordPress users and usermeta tables that would otherwise + * be determined by the prefix. + * + * The scope argument can take one of the following: + * + * 'all' - returns 'all' and 'global' tables. No old tables are returned. + * 'blog' - returns the blog-level tables for the queried blog. + * 'global' - returns the global tables for the installation, returning multisite tables only if running multisite. + * 'ms_global' - returns the multisite global tables, regardless if current installation is multisite. + * 'old' - returns tables which are deprecated. + * + * @since 3.0.0 + * @uses wpdb::$tables + * @uses wpdb::$old_tables + * @uses wpdb::$global_tables + * @uses wpdb::$ms_global_tables + * + * @param string $scope Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all. + * @param bool $prefix Optional. Whether to include table prefixes. Default true. If blog + * prefix is requested, then the custom users and usermeta tables will be mapped. + * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested. + * @return array Table names. When a prefix is requested, the key is the unprefixed table name. + */ + public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) { + switch ( $scope ) { + case 'all' : + $tables = array_merge( $this->global_tables, $this->tables ); + if ( is_multisite() ) + $tables = array_merge( $tables, $this->ms_global_tables ); + break; + case 'blog' : + $tables = $this->tables; + break; + case 'global' : + $tables = $this->global_tables; + if ( is_multisite() ) + $tables = array_merge( $tables, $this->ms_global_tables ); + break; + case 'ms_global' : + $tables = $this->ms_global_tables; + break; + case 'old' : + $tables = $this->old_tables; + break; + default : + return array(); + } + + if ( $prefix ) { + if ( ! $blog_id ) + $blog_id = $this->blogid; + $blog_prefix = $this->get_blog_prefix( $blog_id ); + $base_prefix = $this->base_prefix; + $global_tables = array_merge( $this->global_tables, $this->ms_global_tables ); + foreach ( $tables as $k => $table ) { + if ( in_array( $table, $global_tables ) ) + $tables[ $table ] = $base_prefix . $table; + else + $tables[ $table ] = $blog_prefix . $table; + unset( $tables[ $k ] ); + } + + if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) ) + $tables['users'] = CUSTOM_USER_TABLE; + + if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) ) + $tables['usermeta'] = CUSTOM_USER_META_TABLE; + } + + return $tables; + } + /** * Selects a database using the current database connection. * @@ -451,38 +968,97 @@ class wpdb { * @since 0.71 * * @param string $db MySQL database name + * @param resource $dbh Optional link identifier. * @return null Always null. */ - function select($db) { - if (!@mysql_select_db($db, $this->dbh)) { + public function select( $db, $dbh = null ) { + if ( is_null($dbh) ) + $dbh = $this->dbh; + + if ( $this->use_mysqli ) { + $success = @mysqli_select_db( $dbh, $db ); + } else { + $success = @mysql_select_db( $db, $dbh ); + } + if ( ! $success ) { $this->ready = false; - $this->bail(sprintf(/*WP_I18N_DB_SELECT_DB*/' -We were able to connect to the database server (which means your username and password is okay) but not able to select the %1$s
database.
%2$s
have permission to use the %1$s
database?username_%1$s
. Could that be the problem?If you don\'t know how to setup a database you should contact your host. If all else fails you may find help at the WordPress Support Forums.
'/*/WP_I18N_DB_SELECT_DB*/, $db, $this->dbuser), 'db_select_fail'); +If you don\'t know how to set up a database you should contact your host. If all else fails you may find help at the WordPress Support Forums.
' ), htmlspecialchars( $db, ENT_QUOTES ), htmlspecialchars( $this->dbuser, ENT_QUOTES ) ), 'db_select_fail' ); + } return; } - } + } + + /** + * Do not use, deprecated. + * + * Use esc_sql() or wpdb::prepare() instead. + * + * @since 2.8.0 + * @deprecated 3.6.0 + * @see wpdb::prepare + * @see esc_sql() + * @access private + * + * @param string $string + * @return string + */ + function _weak_escape( $string ) { + if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) + _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); + return addslashes( $string ); + } + + /** + * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() + * + * @see mysqli_real_escape_string() + * @see mysql_real_escape_string() + * @since 2.8.0 + * @access private + * + * @param string $string to escape + * @return string escaped + */ + function _real_escape( $string ) { + if ( $this->dbh ) { + if ( $this->use_mysqli ) { + return mysqli_real_escape_string( $this->dbh, $string ); + } else { + return mysql_real_escape_string( $string, $this->dbh ); + } + } - function _weak_escape($string) { - return addslashes($string); - } - - function _real_escape($string) { - if ( $this->dbh && $this->real_escape ) - return mysql_real_escape_string( $string, $this->dbh ); - else - return addslashes( $string ); + $class = get_class( $this ); + if ( function_exists( '__' ) ) { + _doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), E_USER_NOTICE ); + } else { + _doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), E_USER_NOTICE ); + } + return addslashes( $string ); } - function _escape($data) { - if ( is_array($data) ) { - foreach ( (array) $data as $k => $v ) { + /** + * Escape data. Works on arrays. + * + * @uses wpdb::_real_escape() + * @since 2.8.0 + * @access private + * + * @param string|array $data + * @return string|array escaped + */ + function _escape( $data ) { + if ( is_array( $data ) ) { + foreach ( $data as $k => $v ) { if ( is_array($v) ) $data[$k] = $this->_escape( $v ); else @@ -496,23 +1072,30 @@ class wpdb { } /** - * Escapes content for insertion into the database using addslashes(), for security + * Do not use, deprecated. + * + * Use esc_sql() or wpdb::prepare() instead. * * @since 0.71 + * @deprecated 3.6.0 + * @see wpdb::prepare() + * @see esc_sql() * - * @param string|array $data - * @return string query safe string + * @param mixed $data + * @return mixed */ - function escape($data) { - if ( is_array($data) ) { - foreach ( (array) $data as $k => $v ) { - if ( is_array($v) ) - $data[$k] = $this->escape( $v ); + public function escape( $data ) { + if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) + _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); + if ( is_array( $data ) ) { + foreach ( $data as $k => $v ) { + if ( is_array( $v ) ) + $data[$k] = $this->escape( $v, 'recursive' ); else - $data[$k] = $this->_weak_escape( $v ); + $data[$k] = $this->_weak_escape( $v, 'internal' ); } } else { - $data = $this->_weak_escape( $data ); + $data = $this->_weak_escape( $data, 'internal' ); } return $data; @@ -521,18 +1104,29 @@ class wpdb { /** * Escapes content by reference for insertion into the database, for security * + * @uses wpdb::_real_escape() * @since 2.3.0 - * - * @param string $s + * @param string $string to escape + * @return void */ - function escape_by_ref(&$string) { - $string = $this->_real_escape( $string ); + public function escape_by_ref( &$string ) { + if ( ! is_float( $string ) ) + $string = $this->_real_escape( $string ); } /** - * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. + * Prepares a SQL query for safe execution. Uses sprintf()-like syntax. + * + * The following directives can be used in the query format string: + * %d (integer) + * %f (float) + * %s (string) + * %% (literal percentage sign - no argument needed) + * + * All of %d, %f, and %s are to be left unquoted in the query string and they need an argument passed for them. + * Literals (%) as parts of the query must be properly written as %%. * - * This function only supports a small subset of the sprintf syntax; it only supports %d (decimal number), %s (string). + * This function only supports a small subset of the sprintf syntax; it only supports %d (integer), %f (float), and %s (string). * Does not support sign, padding, alignment, width or precision specifiers. * Does not support argument numbering/swapping. * @@ -540,31 +1134,67 @@ class wpdb { * * Both %d and %s should be left unquoted in the query string. * - *
- * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", "foo", 1337 )
- *
+ * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 )
+ * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
*
* @link http://php.net/sprintf Description of syntax.
* @since 2.3.0
*
* @param string $query Query statement with sprintf()-like placeholders
- * @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()}.
- * @param mixed $args,... further variables to substitute into the query's placeholders if being called like {@link http://php.net/sprintf sprintf()}.
- * @return null|string Sanitized query string
+ * @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()}.
+ * @param mixed $args,... further variables to substitute into the query's placeholders if being called like
+ * {@link http://php.net/sprintf sprintf()}.
+ * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string
+ * if there was something to prepare
*/
- function prepare($query = null) { // ( $query, *$args )
+ public function prepare( $query, $args ) {
if ( is_null( $query ) )
return;
+
+ // This is not meant to be foolproof -- but it will catch obviously incorrect usage.
+ if ( strpos( $query, '%' ) === false ) {
+ _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' );
+ }
+
$args = func_get_args();
- array_shift($args);
+ array_shift( $args );
// If args were passed as an array (as in vsprintf), move them up
- if ( isset($args[0]) && is_array($args[0]) )
+ if ( isset( $args[0] ) && is_array($args[0]) )
$args = $args[0];
- $query = str_replace("'%s'", '%s', $query); // in case someone mistakenly already singlequoted it
- $query = str_replace('"%s"', '%s', $query); // doublequote unquoting
- $query = str_replace('%s', "'%s'", $query); // quote the strings
- array_walk($args, array(&$this, 'escape_by_ref'));
- return @vsprintf($query, $args);
+ $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
+ $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
+ $query = preg_replace( '|(?esc_like( $find ) . $wild;
+ * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
+ *
+ * Example Escape Chain:
+ * $sql = esc_sql( $wpdb->esc_like( $input ) );
+ *
+ * @since 4.0.0
+ * @access public
+ *
+ * @param string $text The raw text to be escaped. The input typed by the user should have no
+ * extra or deleted slashes.
+ * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare()
+ * or real_escape next.
+ */
+ public function esc_like( $text ) {
+ return addcslashes( $text, '_%\\' );
}
/**
@@ -574,45 +1204,52 @@ class wpdb {
* @global array $EZSQL_ERROR Stores error information of query and error string
*
* @param string $str The error to display
- * @return bool False if the showing of errors is disabled.
+ * @return false|null False if the showing of errors is disabled.
*/
- function print_error($str = '') {
+ public function print_error( $str = '' ) {
global $EZSQL_ERROR;
- if (!$str) $str = mysql_error($this->dbh);
- $EZSQL_ERROR[] = array ('query' => $this->last_query, 'error_str' => $str);
+ if ( !$str ) {
+ if ( $this->use_mysqli ) {
+ $str = mysqli_error( $this->dbh );
+ } else {
+ $str = mysql_error( $this->dbh );
+ }
+ }
+ $EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str );
if ( $this->suppress_errors )
return false;
+ wp_load_translations_early();
+
if ( $caller = $this->get_caller() )
- $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);
+ $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller );
else
- $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);
-
- $log_error = true;
- if ( ! function_exists('error_log') )
- $log_error = false;
+ $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query );
- $log_file = @ini_get('error_log');
- if ( !empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file) )
- $log_error = false;
+ error_log( $error_str );
- if ( $log_error )
- @error_log($error_str, 0);
-
- // Is error output turned on or not..
- if ( !$this->show_errors )
+ // Are we showing errors?
+ if ( ! $this->show_errors )
return false;
- $str = htmlspecialchars($str, ENT_QUOTES);
- $query = htmlspecialchars($this->last_query, ENT_QUOTES);
-
// If there is an error then take note of it
- print "WordPress database error: [$str]
- $query
WordPress database error: [$str]
+ $query
This either means that the username and password information in your wp-config.php
file is incorrect or we can't contact the database server at %s
. This could mean your host's database server is down.
If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums.
+" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); + + return false; + } else if ( $this->dbh ) { + $this->has_connected = true; + $this->set_charset( $this->dbh ); + $this->set_sql_mode(); + $this->ready = true; + $this->select( $this->dbname, $this->dbh ); + + return true; + } + + return false; + } + + /** + * Check that the connection to the database is still up. If not, try to reconnect. + * + * If this function is unable to reconnect, it will forcibly die, or if after the + * the template_redirect hook has been fired, return false instead. + * + * If $allow_bail is false, the lack of database connection will need + * to be handled manually. + * + * @since 3.9.0 + * + * @param bool $allow_bail Optional. Allows the function to bail. Default true. + * @return bool|null True if the connection is up. + */ + public function check_connection( $allow_bail = true ) { + if ( $this->use_mysqli ) { + if ( @mysqli_ping( $this->dbh ) ) { + return true; + } + } else { + if ( @mysql_ping( $this->dbh ) ) { + return true; + } + } + + $error_reporting = false; + + // Disable warnings, as we don't want to see a multitude of "unable to connect" messages + if ( WP_DEBUG ) { + $error_reporting = error_reporting(); + error_reporting( $error_reporting & ~E_WARNING ); + } + + for ( $tries = 1; $tries <= $this->reconnect_retries; $tries++ ) { + // On the last try, re-enable warnings. We want to see a single instance of the + // "unable to connect" message on the bail() screen, if it appears. + if ( $this->reconnect_retries === $tries && WP_DEBUG ) { + error_reporting( $error_reporting ); + } + + if ( $this->db_connect( false ) ) { + if ( $error_reporting ) { + error_reporting( $error_reporting ); + } + + return true; + } + + sleep( 1 ); + } + + // If template_redirect has already happened, it's too late for wp_die()/dead_db(). + // Let's just return and hope for the best. + if ( did_action( 'template_redirect' ) ) { + return false; + } + + if ( ! $allow_bail ) { + return false; + } + + // We weren't able to reconnect, so we better bail. + $this->bail( sprintf( ( " +This means that we lost contact with the database server at %s
. This could mean your host's database server is down.
If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the WordPress Support Forums.
+" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); + + // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily). + dead_db(); } /** @@ -677,20 +1536,26 @@ class wpdb { * * @since 0.71 * - * @param string $query + * @param string $query Database query * @return int|false Number of rows affected/selected or false on error */ - function query($query) { - if ( ! $this->ready ) + public function query( $query ) { + if ( ! $this->ready ) { return false; + } - // filter the query, if filters are available - // NOTE: some queries are made before the plugins have been loaded, and thus cannot be filtered with this method - if ( function_exists('apply_filters') ) - $query = apply_filters('query', $query); + /** + * Filter the database query. + * + * Some queries are made before the plugins have been loaded, + * and thus cannot be filtered with this method. + * + * @since 2.1.0 + * + * @param string $query Database query. + */ + $query = apply_filters( 'query', $query ); - // initialise return - $return_val = 0; $this->flush(); // Log how the function was called @@ -699,113 +1564,219 @@ class wpdb { // Keep track of the last query for debug.. $this->last_query = $query; - // Perform the query via std mysql_query function.. - if ( defined('SAVEQUERIES') && SAVEQUERIES ) - $this->timer_start(); + $this->_do_query( $query ); - $this->result = @mysql_query($query, $this->dbh); - ++$this->num_queries; + // MySQL server has gone away, try to reconnect + $mysql_errno = 0; + if ( ! empty( $this->dbh ) ) { + if ( $this->use_mysqli ) { + $mysql_errno = mysqli_errno( $this->dbh ); + } else { + $mysql_errno = mysql_errno( $this->dbh ); + } + } - if ( defined('SAVEQUERIES') && SAVEQUERIES ) - $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); + if ( empty( $this->dbh ) || 2006 == $mysql_errno ) { + if ( $this->check_connection() ) { + $this->_do_query( $query ); + } else { + $this->insert_id = 0; + return false; + } + } // If there is an error then take note of it.. - if ( $this->last_error = mysql_error($this->dbh) ) { + if ( $this->use_mysqli ) { + $this->last_error = mysqli_error( $this->dbh ); + } else { + $this->last_error = mysql_error( $this->dbh ); + } + + if ( $this->last_error ) { + // Clear insert_id on a subsequent failed insert. + if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) ) + $this->insert_id = 0; + $this->print_error(); return false; } - if ( preg_match("/^\\s*(insert|delete|update|replace|alter) /i",$query) ) { - $this->rows_affected = mysql_affected_rows($this->dbh); + if ( preg_match( '/^\s*(create|alter|truncate|drop)\s/i', $query ) ) { + $return_val = $this->result; + } elseif ( preg_match( '/^\s*(insert|delete|update|replace)\s/i', $query ) ) { + if ( $this->use_mysqli ) { + $this->rows_affected = mysqli_affected_rows( $this->dbh ); + } else { + $this->rows_affected = mysql_affected_rows( $this->dbh ); + } // Take note of the insert_id - if ( preg_match("/^\\s*(insert|replace) /i",$query) ) { - $this->insert_id = mysql_insert_id($this->dbh); + if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) { + if ( $this->use_mysqli ) { + $this->insert_id = mysqli_insert_id( $this->dbh ); + } else { + $this->insert_id = mysql_insert_id( $this->dbh ); + } } // Return number of rows affected $return_val = $this->rows_affected; } else { - $i = 0; - while ($i < @mysql_num_fields($this->result)) { - $this->col_info[$i] = @mysql_fetch_field($this->result); - $i++; - } $num_rows = 0; - while ( $row = @mysql_fetch_object($this->result) ) { - $this->last_result[$num_rows] = $row; - $num_rows++; + if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { + while ( $row = @mysqli_fetch_object( $this->result ) ) { + $this->last_result[$num_rows] = $row; + $num_rows++; + } + } else if ( is_resource( $this->result ) ) { + while ( $row = @mysql_fetch_object( $this->result ) ) { + $this->last_result[$num_rows] = $row; + $num_rows++; + } } - @mysql_free_result($this->result); - // Log number of rows the query returned + // and return number of rows selected $this->num_rows = $num_rows; - - // Return number of rows selected - $return_val = $this->num_rows; + $return_val = $num_rows; } return $return_val; } + /** + * Internal function to perform the mysql_query() call. + * + * @since 3.9.0 + * + * @access private + * @see wpdb::query() + * + * @param string $query The query to run. + */ + private function _do_query( $query ) { + if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { + $this->timer_start(); + } + + if ( $this->use_mysqli ) { + $this->result = @mysqli_query( $this->dbh, $query ); + } else { + $this->result = @mysql_query( $query, $this->dbh ); + } + $this->num_queries++; + + if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { + $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); + } + } + /** * Insert a row into a table. * - *
- * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
- *
+ * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
+ * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
*
* @since 2.5.0
* @see wpdb::prepare()
+ * @see wpdb::$field_types
+ * @see wp_set_wpdb_vars()
*
* @param string $table table name
- * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
- * @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.
+ * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
+ * @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', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
* @return int|false The number of rows inserted, or false on error.
*/
- function insert($table, $data, $format = null) {
+ public function insert( $table, $data, $format = null ) {
+ return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' );
+ }
+
+ /**
+ * Replace a row into a table.
+ *
+ * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
+ * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
+ *
+ * @since 3.0.0
+ * @see wpdb::prepare()
+ * @see wpdb::$field_types
+ * @see wp_set_wpdb_vars()
+ *
+ * @param string $table table name
+ * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
+ * @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', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
+ * @return int|false The number of rows affected, or false on error.
+ */
+ public function replace( $table, $data, $format = null ) {
+ return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' );
+ }
+
+ /**
+ * Helper function for insert and replace.
+ *
+ * Runs an insert or replace query based on $type argument.
+ *
+ * @access private
+ * @since 3.0.0
+ * @see wpdb::prepare()
+ * @see wpdb::$field_types
+ * @see wp_set_wpdb_vars()
+ *
+ * @param string $table table name
+ * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
+ * @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', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
+ * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT.
+ * @return int|false The number of rows affected, or false on error.
+ */
+ function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
+ if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) )
+ return false;
+ $this->insert_id = 0;
$formats = $format = (array) $format;
- $fields = array_keys($data);
+ $fields = array_keys( $data );
$formatted_fields = array();
foreach ( $fields as $field ) {
- if ( !empty($format) )
- $form = ( $form = array_shift($formats) ) ? $form : $format[0];
- elseif ( isset($this->field_types[$field]) )
+ if ( !empty( $format ) )
+ $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
+ elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
$formatted_fields[] = $form;
}
- $sql = "INSERT INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES ('" . implode( "','", $formatted_fields ) . "')";
- return $this->query( $this->prepare( $sql, $data) );
+ $sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
+ return $this->query( $this->prepare( $sql, $data ) );
}
-
/**
* Update a row in the table
*
- *
- * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
- *
+ * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) )
+ * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
*
* @since 2.5.0
* @see wpdb::prepare()
+ * @see wpdb::$field_types
+ * @see wp_set_wpdb_vars()
*
* @param string $table table name
- * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
- * @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".
- * @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.
- * @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.
+ * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
+ * @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".
+ * @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', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
+ * @param array|string $where_format 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', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings.
* @return int|false The number of rows updated, or false on error.
*/
- function update($table, $data, $where, $format = null, $where_format = null) {
- if ( !is_array( $where ) )
+ public function update( $table, $data, $where, $format = null, $where_format = null ) {
+ if ( ! is_array( $data ) || ! is_array( $where ) )
return false;
$formats = $format = (array) $format;
$bits = $wheres = array();
- foreach ( (array) array_keys($data) as $field ) {
- if ( !empty($format) )
- $form = ( $form = array_shift($formats) ) ? $form : $format[0];
+ foreach ( (array) array_keys( $data ) as $field ) {
+ if ( !empty( $format ) )
+ $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
elseif ( isset($this->field_types[$field]) )
$form = $this->field_types[$field];
else
@@ -814,10 +1785,10 @@ class wpdb {
}
$where_formats = $where_format = (array) $where_format;
- foreach ( (array) array_keys($where) as $field ) {
- if ( !empty($where_format) )
- $form = ( $form = array_shift($where_formats) ) ? $form : $where_format[0];
- elseif ( isset($this->field_types[$field]) )
+ foreach ( (array) array_keys( $where ) as $field ) {
+ if ( !empty( $where_format ) )
+ $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
+ elseif ( isset( $this->field_types[$field] ) )
$form = $this->field_types[$field];
else
$form = '%s';
@@ -825,7 +1796,47 @@ class wpdb {
}
$sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
- return $this->query( $this->prepare( $sql, array_merge(array_values($data), array_values($where))) );
+ return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
+ }
+
+ /**
+ * Delete a row in the table
+ *
+ * wpdb::delete( 'table', array( 'ID' => 1 ) )
+ * wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
+ *
+ * @since 3.4.0
+ * @see wpdb::prepare()
+ * @see wpdb::$field_types
+ * @see wp_set_wpdb_vars()
+ *
+ * @param string $table table name
+ * @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".
+ * @param array|string $where_format 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', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types.
+ * @return int|false The number of rows updated, or false on error.
+ */
+ public function delete( $table, $where, $where_format = null ) {
+ if ( ! is_array( $where ) )
+ return false;
+
+ $wheres = array();
+
+ $where_formats = $where_format = (array) $where_format;
+
+ foreach ( array_keys( $where ) as $field ) {
+ if ( !empty( $where_format ) ) {
+ $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
+ } elseif ( isset( $this->field_types[ $field ] ) ) {
+ $form = $this->field_types[ $field ];
+ } else {
+ $form = '%s';
+ }
+
+ $wheres[] = "$field = $form";
+ }
+
+ $sql = "DELETE FROM $table WHERE " . implode( ' AND ', $wheres );
+ return $this->query( $this->prepare( $sql, $where ) );
}
/**
@@ -837,23 +1848,25 @@ class wpdb {
*
* @since 0.71
*
- * @param string|null $query SQL query. If null, use the result from the previous query.
- * @param int $x (optional) Column of value to return. Indexed from 0.
- * @param int $y (optional) Row of value to return. Indexed from 0.
- * @return string Database query result
+ * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
+ * @param int $x Optional. Column of value to return. Indexed from 0.
+ * @param int $y Optional. Row of value to return. Indexed from 0.
+ * @return string|null Database query result (as string), or null on failure
*/
- function get_var($query=null, $x = 0, $y = 0) {
- $this->func_call = "\$db->get_var(\"$query\",$x,$y)";
- if ( $query )
- $this->query($query);
+ public function get_var( $query = null, $x = 0, $y = 0 ) {
+ $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
+
+ if ( $query ) {
+ $this->query( $query );
+ }
// Extract var out of cached results based x,y vals
if ( !empty( $this->last_result[$y] ) ) {
- $values = array_values(get_object_vars($this->last_result[$y]));
+ $values = array_values( get_object_vars( $this->last_result[$y] ) );
}
// If there is a value return it else return null
- return (isset($values[$x]) && $values[$x]!=='') ? $values[$x] : null;
+ return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
}
/**
@@ -864,28 +1877,33 @@ class wpdb {
* @since 0.71
*
* @param string|null $query SQL query.
- * @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.
- * @param int $y (optional) Row to return. Indexed from 0.
- * @return mixed Database query result in format specifed by $output
+ * @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.
+ * @param int $y Optional. Row to return. Indexed from 0.
+ * @return mixed Database query result in format specified by $output or null on failure
*/
- function get_row($query = null, $output = OBJECT, $y = 0) {
+ public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
- if ( $query )
- $this->query($query);
- else
+ if ( $query ) {
+ $this->query( $query );
+ } else {
return null;
+ }
- if ( !isset($this->last_result[$y]) )
+ if ( !isset( $this->last_result[$y] ) )
return null;
if ( $output == OBJECT ) {
return $this->last_result[$y] ? $this->last_result[$y] : null;
} elseif ( $output == ARRAY_A ) {
- return $this->last_result[$y] ? get_object_vars($this->last_result[$y]) : null;
+ return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
} elseif ( $output == ARRAY_N ) {
- return $this->last_result[$y] ? array_values(get_object_vars($this->last_result[$y])) : null;
+ return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
+ } elseif ( strtoupper( $output ) === OBJECT ) {
+ // Back compat for OBJECT being previously case insensitive.
+ return $this->last_result[$y] ? $this->last_result[$y] : null;
} else {
- $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*/);
+ $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" );
}
}
@@ -898,18 +1916,19 @@ class wpdb {
*
* @since 0.71
*
- * @param string|null $query SQL query. If null, use the result from the previous query.
- * @param int $x Column to return. Indexed from 0.
- * @return array Database query result. Array indexed from 0 by SQL result row number.
+ * @param string|null $query Optional. SQL query. Defaults to previous query.
+ * @param int $x Optional. Column to return. Indexed from 0.
+ * @return array Database query result. Array indexed from 0 by SQL result row number.
*/
- function get_col($query = null , $x = 0) {
- if ( $query )
- $this->query($query);
+ public function get_col( $query = null , $x = 0 ) {
+ if ( $query ) {
+ $this->query( $query );
+ }
$new_array = array();
// Extract the column values
- for ( $i=0; $i < count($this->last_result); $i++ ) {
- $new_array[$i] = $this->get_var(null, $x, $i);
+ for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
+ $new_array[$i] = $this->get_var( null, $x, $i );
}
return $new_array;
}
@@ -922,17 +1941,21 @@ class wpdb {
* @since 0.71
*
* @param string $query SQL query.
- * @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.
+ * @param string $output Optional. Any 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.
* @return mixed Database query results
*/
- function get_results($query = null, $output = OBJECT) {
+ public function get_results( $query = null, $output = OBJECT ) {
$this->func_call = "\$db->get_results(\"$query\", $output)";
- if ( $query )
- $this->query($query);
- else
+ if ( $query ) {
+ $this->query( $query );
+ } else {
return null;
+ }
+ $new_array = array();
if ( $output == OBJECT ) {
// Return an integer-keyed array of row objects
return $this->last_result;
@@ -940,26 +1963,51 @@ class wpdb {
// Return an array of row objects with keys from column 1
// (Duplicates are discarded)
foreach ( $this->last_result as $row ) {
- $key = array_shift( get_object_vars( $row ) );
- if ( !isset( $new_array[ $key ] ) )
+ $var_by_ref = get_object_vars( $row );
+ $key = array_shift( $var_by_ref );
+ if ( ! isset( $new_array[ $key ] ) )
$new_array[ $key ] = $row;
}
return $new_array;
} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
// Return an integer-keyed array of...
if ( $this->last_result ) {
- $i = 0;
foreach( (array) $this->last_result as $row ) {
if ( $output == ARRAY_N ) {
// ...integer-keyed row arrays
- $new_array[$i] = array_values( get_object_vars( $row ) );
+ $new_array[] = array_values( get_object_vars( $row ) );
} else {
// ...column name-keyed row arrays
- $new_array[$i] = get_object_vars( $row );
+ $new_array[] = get_object_vars( $row );
}
- ++$i;
}
- return $new_array;
+ }
+ return $new_array;
+ } elseif ( strtoupper( $output ) === OBJECT ) {
+ // Back compat for OBJECT being previously case insensitive.
+ return $this->last_result;
+ }
+ return null;
+ }
+
+ /**
+ * Load the column metadata from the last query.
+ *
+ * @since 3.5.0
+ *
+ * @access protected
+ */
+ protected function load_col_info() {
+ if ( $this->col_info )
+ return;
+
+ if ( $this->use_mysqli ) {
+ for ( $i = 0; $i < @mysqli_num_fields( $this->result ); $i++ ) {
+ $this->col_info[ $i ] = @mysqli_fetch_field( $this->result );
+ }
+ } else {
+ for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) {
+ $this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i );
}
}
}
@@ -969,14 +2017,17 @@ class wpdb {
*
* @since 0.71
*
- * @param string $info_type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
- * @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
+ * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
+ * @param int $col_offset Optional. 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
* @return mixed Column Results
*/
- function get_col_info($info_type = 'name', $col_offset = -1) {
+ public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
+ $this->load_col_info();
+
if ( $this->col_info ) {
if ( $col_offset == -1 ) {
$i = 0;
+ $new_array = array();
foreach( (array) $this->col_info as $col ) {
$new_array[$i] = $col->{$info_type};
$i++;
@@ -993,12 +2044,10 @@ class wpdb {
*
* @since 1.5.0
*
- * @return true
+ * @return bool
*/
- function timer_start() {
- $mtime = microtime();
- $mtime = explode(' ', $mtime);
- $this->time_start = $mtime[1] + $mtime[0];
+ public function timer_start() {
+ $this->time_start = microtime( true );
return true;
}
@@ -1007,30 +2056,26 @@ class wpdb {
*
* @since 1.5.0
*
- * @return int Total time spent on the query, in milliseconds
+ * @return float Total time spent on the query, in seconds
*/
- function timer_stop() {
- $mtime = microtime();
- $mtime = explode(' ', $mtime);
- $time_end = $mtime[1] + $mtime[0];
- $time_total = $time_end - $this->time_start;
- return $time_total;
+ public function timer_stop() {
+ return ( microtime( true ) - $this->time_start );
}
/**
* Wraps errors in a nice header and footer and dies.
*
- * Will not die if wpdb::$show_errors is true
+ * Will not die if wpdb::$show_errors is false.
*
* @since 1.5.0
*
* @param string $message The Error message
- * @param string $error_code (optional) A Computer readable string to identify the error.
+ * @param string $error_code Optional. A Computer readable string to identify the error.
* @return false|void
*/
- function bail($message, $error_code = '500') {
+ public function bail( $message, $error_code = '500' ) {
if ( !$this->show_errors ) {
- if ( class_exists('WP_Error') )
+ if ( class_exists( 'WP_Error' ) )
$this->error = new WP_Error($error_code, $message);
else
$this->error = $message;
@@ -1040,50 +2085,81 @@ class wpdb {
}
/**
- * Whether or not MySQL database is at least the required minimum version.
+ * Whether MySQL database is at least the required minimum version.
*
* @since 2.5.0
* @uses $wp_version
+ * @uses $required_mysql_version
*
* @return WP_Error
*/
- function check_database_version()
- {
- global $wp_version;
- // Make sure the server has MySQL 4.1.2
- if ( version_compare($this->db_version(), '4.1.2', '<') )
- return new WP_Error('database_version',sprintf(__('ERROR: WordPress %s requires MySQL 4.1.2 or higher'), $wp_version));
+ public function check_database_version() {
+ global $wp_version, $required_mysql_version;
+ // Make sure the server has the required MySQL version
+ if ( version_compare($this->db_version(), $required_mysql_version, '<') )
+ return new WP_Error('database_version', sprintf( __( 'ERROR: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version ));
}
/**
- * Whether of not the database supports collation.
+ * Whether the database supports collation.
*
* Called when WordPress is generating the table scheme.
*
* @since 2.5.0
+ * @deprecated 3.5.0
+ * @deprecated Use wpdb::has_cap( 'collation' )
*
* @return bool True if collation is supported, false if version does not
*/
- function supports_collation() {
+ public function supports_collation() {
+ _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' );
return $this->has_cap( 'collation' );
}
/**
- * Generic function to determine if a database supports a particular feature
- * @param string $db_cap the feature
- * @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.
- * @return bool
+ * The database character collate.
+ *
+ * @since 3.5.0
+ *
+ * @return string The database character collate.
+ */
+ public function get_charset_collate() {
+ $charset_collate = '';
+
+ if ( ! empty( $this->charset ) )
+ $charset_collate = "DEFAULT CHARACTER SET $this->charset";
+ if ( ! empty( $this->collate ) )
+ $charset_collate .= " COLLATE $this->collate";
+
+ return $charset_collate;
+ }
+
+ /**
+ * Determine if a database supports a particular feature.
+ *
+ * @since 2.7.0
+ * @since 4.1.0 Support was added for the 'utf8mb4' feature.
+ *
+ * @see wpdb::db_version()
+ *
+ * @param string $db_cap The feature to check for. Accepts 'collation',
+ * 'group_concat', 'subqueries', 'set_charset',
+ * or 'utf8mb4'.
+ * @return bool Whether the database feature is supported, false otherwise.
*/
- function has_cap( $db_cap ) {
+ public function has_cap( $db_cap ) {
$version = $this->db_version();
- switch ( strtolower( $db_cap ) ) :
- case 'collation' : // @since 2.5.0
- case 'group_concat' : // @since 2.7
- case 'subqueries' : // @since 2.7
- return version_compare($version, '4.1', '>=');
- break;
- endswitch;
+ switch ( strtolower( $db_cap ) ) {
+ case 'collation' : // @since 2.5.0
+ case 'group_concat' : // @since 2.7.0
+ case 'subqueries' : // @since 2.7.0
+ return version_compare( $version, '4.1', '>=' );
+ case 'set_charset' :
+ return version_compare( $version, '5.0.7', '>=' );
+ case 'utf8mb4' : // @since 4.1.0
+ return version_compare( $version, '5.5.3', '>=' );
+ }
return false;
}
@@ -1091,51 +2167,30 @@ class wpdb {
/**
* Retrieve the name of the function that called wpdb.
*
- * Requires PHP 4.3 and searches up the list of functions until it reaches
+ * Searches up the list of functions until it reaches
* the one that would most logically had called this method.
*
* @since 2.5.0
*
* @return string The name of the calling function
*/
- function get_caller() {
- // requires PHP 4.3+
- if ( !is_callable('debug_backtrace') )
- return '';
-
- $bt = debug_backtrace();
- $caller = array();
-
- $bt = array_reverse( $bt );
- foreach ( (array) $bt as $call ) {
- if ( @$call['class'] == __CLASS__ )
- continue;
- $function = $call['function'];
- if ( isset( $call['class'] ) )
- $function = $call['class'] . "->$function";
- $caller[] = $function;
- }
- $caller = join( ', ', $caller );
-
- return $caller;
+ public function get_caller() {
+ return wp_debug_backtrace_summary( __CLASS__ );
}
/**
- * The database version number
- * @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.
- * @return false|string false on failure, version number on success
+ * The database version number.
+ *
+ * @since 2.7.0
+ *
+ * @return null|string Null on failure, version number on success.
*/
- function db_version() {
- return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ));
+ public function db_version() {
+ if ( $this->use_mysqli ) {
+ $server_info = mysqli_get_server_info( $this->dbh );
+ } else {
+ $server_info = mysql_get_server_info( $this->dbh );
+ }
+ return preg_replace( '/[^0-9.].*/', '', $server_info );
}
}
-
-if ( ! isset($wpdb) ) {
- /**
- * WordPress Database Object, if it isn't set already in wp-content/db.php
- * @global object $wpdb Creates a new wpdb object based on wp-config.php Constants for the database
- * @since 0.71
- */
- $wpdb = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
-}
-?>