wp/wp-includes/wp-db.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
--- a/wp/wp-includes/wp-db.php	Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-includes/wp-db.php	Tue Sep 27 16:37:53 2022 +0200
@@ -59,6 +59,7 @@
 	 * Default is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY evaluate to true.
 	 *
 	 * @since 0.71
+	 *
 	 * @var bool
 	 */
 	public $show_errors = false;
@@ -67,6 +68,7 @@
 	 * Whether to suppress errors during the DB bootstrapping. Default false.
 	 *
 	 * @since 2.5.0
+	 *
 	 * @var bool
 	 */
 	public $suppress_errors = false;
@@ -75,6 +77,7 @@
 	 * The error encountered during the last query.
 	 *
 	 * @since 2.5.0
+	 *
 	 * @var string
 	 */
 	public $last_error = '';
@@ -83,6 +86,7 @@
 	 * The number of queries made.
 	 *
 	 * @since 1.2.0
+	 *
 	 * @var int
 	 */
 	public $num_queries = 0;
@@ -91,6 +95,7 @@
 	 * Count of rows returned by the last query.
 	 *
 	 * @since 0.71
+	 *
 	 * @var int
 	 */
 	public $num_rows = 0;
@@ -99,6 +104,7 @@
 	 * Count of rows affected by the last query.
 	 *
 	 * @since 0.71
+	 *
 	 * @var int
 	 */
 	public $rows_affected = 0;
@@ -107,6 +113,7 @@
 	 * The ID generated for an AUTO_INCREMENT column by the last query (usually INSERT).
 	 *
 	 * @since 0.71
+	 *
 	 * @var int
 	 */
 	public $insert_id = 0;
@@ -115,6 +122,7 @@
 	 * The last query made.
 	 *
 	 * @since 0.71
+	 *
 	 * @var string
 	 */
 	public $last_query;
@@ -123,15 +131,26 @@
 	 * Results of the last query.
 	 *
 	 * @since 0.71
-	 * @var array|null
+	 *
+	 * @var stdClass[]|null
 	 */
 	public $last_result;
 
 	/**
-	 * MySQL result, which is either a resource or boolean.
+	 * Database query result.
+	 *
+	 * Possible values:
+	 *
+	 * - For successful SELECT, SHOW, DESCRIBE, or EXPLAIN queries:
+	 *   - `mysqli_result` instance when the `mysqli` driver is in use
+	 *   - `resource` when the older `mysql` driver is in use
+	 * - `true` for other query types that were successful
+	 * - `null` if a query is yet to be made or if the result has since been flushed
+	 * - `false` if the query returned an error
 	 *
 	 * @since 0.71
-	 * @var mixed
+	 *
+	 * @var mysqli_result|resource|bool|null
 	 */
 	protected $result;
 
@@ -139,22 +158,25 @@
 	 * Cached column info, for sanity checking data before inserting.
 	 *
 	 * @since 4.2.0
+	 *
 	 * @var array
 	 */
 	protected $col_meta = array();
 
 	/**
-	 * Calculated character sets on tables.
+	 * Calculated character sets keyed by table name.
 	 *
 	 * @since 4.2.0
-	 * @var array
+	 *
+	 * @var string[]
 	 */
 	protected $table_charset = array();
 
 	/**
-	 * Whether text fields in the current query need to be sanity checked. Default false.
+	 * Whether text fields in the current query need to be sanity checked.
 	 *
 	 * @since 4.2.0
+	 *
 	 * @var bool
 	 */
 	protected $check_current_query = true;
@@ -163,6 +185,7 @@
 	 * Flag to ensure we don't run into recursion problems when checking the collation.
 	 *
 	 * @since 4.2.0
+	 *
 	 * @see wpdb::check_safe_collation()
 	 * @var bool
 	 */
@@ -172,6 +195,7 @@
 	 * Saved info on the table column.
 	 *
 	 * @since 0.71
+	 *
 	 * @var array
 	 */
 	protected $col_info;
@@ -185,7 +209,7 @@
 	 * @since 5.3.0 The fifth element in each query log was added to record custom data.
 	 *
 	 * @var array[] {
-	 *     Array of queries that were executed.
+	 *     Array of arrays containing information about queries that were executed.
 	 *
 	 *     @type array ...$0 {
 	 *         Data for each query.
@@ -204,18 +228,20 @@
 	 * The number of times to retry reconnecting before dying. Default 5.
 	 *
 	 * @since 3.9.0
+	 *
 	 * @see wpdb::check_connection()
 	 * @var int
 	 */
 	protected $reconnect_retries = 5;
 
 	/**
-	 * WordPress table prefix
+	 * WordPress table prefix.
 	 *
 	 * You can set this to have multiple WordPress installations in a single database.
 	 * The second reason is for possible security precautions.
 	 *
 	 * @since 2.5.0
+	 *
 	 * @var string
 	 */
 	public $prefix = '';
@@ -224,6 +250,7 @@
 	 * WordPress base table prefix.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $base_prefix;
@@ -232,6 +259,7 @@
 	 * Whether the database queries are ready to start executing.
 	 *
 	 * @since 2.3.2
+	 *
 	 * @var bool
 	 */
 	public $ready = false;
@@ -240,6 +268,7 @@
 	 * Blog ID.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var int
 	 */
 	public $blogid = 0;
@@ -248,16 +277,18 @@
 	 * Site ID.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var int
 	 */
 	public $siteid = 0;
 
 	/**
-	 * List of WordPress per-blog tables.
+	 * List of WordPress per-site tables.
 	 *
 	 * @since 2.5.0
+	 *
 	 * @see wpdb::tables()
-	 * @var array
+	 * @var string[]
 	 */
 	public $tables = array(
 		'posts',
@@ -278,8 +309,9 @@
 	 * 'categories', 'post2cat', and 'link2cat' were deprecated in 2.3.0, db version 5539.
 	 *
 	 * @since 2.9.0
+	 *
 	 * @see wpdb::tables()
-	 * @var array
+	 * @var string[]
 	 */
 	public $old_tables = array( 'categories', 'post2cat', 'link2cat' );
 
@@ -287,8 +319,9 @@
 	 * List of WordPress global tables.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @see wpdb::tables()
-	 * @var array
+	 * @var string[]
 	 */
 	public $global_tables = array( 'users', 'usermeta' );
 
@@ -296,8 +329,9 @@
 	 * List of Multisite global tables.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @see wpdb::tables()
-	 * @var array
+	 * @var string[]
 	 */
 	public $ms_global_tables = array(
 		'blogs',
@@ -313,6 +347,7 @@
 	 * WordPress Comments table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $comments;
@@ -321,6 +356,7 @@
 	 * WordPress Comment Metadata table.
 	 *
 	 * @since 2.9.0
+	 *
 	 * @var string
 	 */
 	public $commentmeta;
@@ -329,6 +365,7 @@
 	 * WordPress Links table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $links;
@@ -337,6 +374,7 @@
 	 * WordPress Options table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $options;
@@ -345,6 +383,7 @@
 	 * WordPress Post Metadata table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $postmeta;
@@ -353,6 +392,7 @@
 	 * WordPress Posts table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $posts;
@@ -361,6 +401,7 @@
 	 * WordPress Terms table.
 	 *
 	 * @since 2.3.0
+	 *
 	 * @var string
 	 */
 	public $terms;
@@ -369,6 +410,7 @@
 	 * WordPress Term Relationships table.
 	 *
 	 * @since 2.3.0
+	 *
 	 * @var string
 	 */
 	public $term_relationships;
@@ -377,6 +419,7 @@
 	 * WordPress Term Taxonomy table.
 	 *
 	 * @since 2.3.0
+	 *
 	 * @var string
 	 */
 	public $term_taxonomy;
@@ -385,6 +428,7 @@
 	 * WordPress Term Meta table.
 	 *
 	 * @since 4.4.0
+	 *
 	 * @var string
 	 */
 	public $termmeta;
@@ -397,6 +441,7 @@
 	 * WordPress User Metadata table.
 	 *
 	 * @since 2.3.0
+	 *
 	 * @var string
 	 */
 	public $usermeta;
@@ -405,6 +450,7 @@
 	 * WordPress Users table.
 	 *
 	 * @since 1.5.0
+	 *
 	 * @var string
 	 */
 	public $users;
@@ -413,6 +459,7 @@
 	 * Multisite Blogs table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $blogs;
@@ -421,6 +468,7 @@
 	 * Multisite Blog Metadata table.
 	 *
 	 * @since 5.1.0
+	 *
 	 * @var string
 	 */
 	public $blogmeta;
@@ -429,6 +477,7 @@
 	 * Multisite Registration Log table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $registration_log;
@@ -437,6 +486,7 @@
 	 * Multisite Signups table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $signups;
@@ -445,6 +495,7 @@
 	 * Multisite Sites table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $site;
@@ -453,6 +504,7 @@
 	 * Multisite Sitewide Terms table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $sitecategories;
@@ -461,6 +513,7 @@
 	 * Multisite Site Metadata table.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $sitemeta;
@@ -472,6 +525,7 @@
 	 * Keys are column names, values are format types: 'ID' => '%d'.
 	 *
 	 * @since 2.8.0
+	 *
 	 * @see wpdb::prepare()
 	 * @see wpdb::insert()
 	 * @see wpdb::update()
@@ -485,6 +539,7 @@
 	 * Database table columns charset.
 	 *
 	 * @since 2.2.0
+	 *
 	 * @var string
 	 */
 	public $charset;
@@ -493,6 +548,7 @@
 	 * Database table columns collate.
 	 *
 	 * @since 2.2.0
+	 *
 	 * @var string
 	 */
 	public $collate;
@@ -501,6 +557,7 @@
 	 * Database Username.
 	 *
 	 * @since 2.9.0
+	 *
 	 * @var string
 	 */
 	protected $dbuser;
@@ -509,6 +566,7 @@
 	 * Database Password.
 	 *
 	 * @since 3.1.0
+	 *
 	 * @var string
 	 */
 	protected $dbpassword;
@@ -517,6 +575,7 @@
 	 * Database Name.
 	 *
 	 * @since 3.1.0
+	 *
 	 * @var string
 	 */
 	protected $dbname;
@@ -525,15 +584,24 @@
 	 * Database Host.
 	 *
 	 * @since 3.1.0
+	 *
 	 * @var string
 	 */
 	protected $dbhost;
 
 	/**
-	 * Database Handle.
+	 * Database handle.
+	 *
+	 * Possible values:
+	 *
+	 * - `mysqli` instance when the `mysqli` driver is in use
+	 * - `resource` when the older `mysql` driver is in use
+	 * - `null` if the connection is yet to be made or has been closed
+	 * - `false` if the connection has failed
 	 *
 	 * @since 0.71
-	 * @var string
+	 *
+	 * @var mysqli|resource|false|null
 	 */
 	protected $dbh;
 
@@ -541,6 +609,7 @@
 	 * A textual description of the last query/get_row/get_var call.
 	 *
 	 * @since 3.0.0
+	 *
 	 * @var string
 	 */
 	public $func_call;
@@ -554,6 +623,7 @@
 	 * will force the checks to occur.
 	 *
 	 * @since 3.3.0
+	 *
 	 * @var bool
 	 */
 	public $is_mysql = null;
@@ -562,7 +632,8 @@
 	 * A list of incompatible SQL modes.
 	 *
 	 * @since 3.9.0
-	 * @var array
+	 *
+	 * @var string[]
 	 */
 	protected $incompatible_modes = array(
 		'NO_ZERO_DATE',
@@ -577,6 +648,7 @@
 	 * Whether to use mysqli over mysql. Default false.
 	 *
 	 * @since 3.9.0
+	 *
 	 * @var bool
 	 */
 	private $use_mysqli = false;
@@ -585,32 +657,52 @@
 	 * Whether we've managed to successfully connect at some point.
 	 *
 	 * @since 3.9.0
+	 *
 	 * @var bool
 	 */
 	private $has_connected = false;
 
 	/**
+	 * Time when the last query was performed.
+	 *
+	 * Only set when `SAVEQUERIES` is defined and truthy.
+	 *
+	 * @since 1.5.0
+	 *
+	 * @var float
+	 */
+	public $time_start = null;
+
+	/**
+	 * The last SQL error that was encountered.
+	 *
+	 * @since 2.5.0
+	 *
+	 * @var WP_Error|string
+	 */
+	public $error = null;
+
+	/**
 	 * Connects to the database server and selects a database.
 	 *
-	 * PHP5 style constructor for compatibility with PHP5. Does the actual setting up
+	 * Does the actual setting up
 	 * of the class properties and connection to the database.
 	 *
 	 * @since 2.0.8
 	 *
 	 * @link https://core.trac.wordpress.org/ticket/3354
-	 * @global string $wp_version The WordPress version string.
-	 *
-	 * @param string $dbuser     MySQL database user.
-	 * @param string $dbpassword MySQL database password.
-	 * @param string $dbname     MySQL database name.
-	 * @param string $dbhost     MySQL database host.
+	 *
+	 * @param string $dbuser     Database user.
+	 * @param string $dbpassword Database password.
+	 * @param string $dbname     Database name.
+	 * @param string $dbhost     Database host.
 	 */
 	public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
 		if ( WP_DEBUG && WP_DEBUG_DISPLAY ) {
 			$this->show_errors();
 		}
 
-		// Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true.
+		// Use the `mysqli` extension if it exists unless `WP_USE_EXT_MYSQL` is defined as true.
 		if ( function_exists( 'mysqli_connect' ) ) {
 			$this->use_mysqli = true;
 
@@ -773,9 +865,9 @@
 	 *
 	 * @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.
+	 * @param mysqli|resource $dbh     The connection returned by `mysqli_connect()` or `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 ) ) {
@@ -983,16 +1075,16 @@
 	/**
 	 * Returns an array of WordPress tables.
 	 *
-	 * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to override the WordPress users
+	 * 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 on multisite.
-	 * 'ms_global' - returns the multisite global tables, regardless if current installation is multisite.
-	 * 'old' - returns tables which are deprecated.
+	 * 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 on multisite.
+	 * - 'ms_global' - returns the multisite global tables, regardless if current installation is multisite.
+	 * - 'old' - returns tables which are deprecated.
 	 *
 	 * @since 3.0.0
 	 *
@@ -1006,8 +1098,8 @@
 	 * @param bool   $prefix  Optional. Whether to include table prefixes. If blog prefix is requested,
 	 *                        then the custom users and usermeta tables will be mapped. Default true.
 	 * @param int    $blog_id Optional. The blog_id to prefix. Used only when prefix is requested.
-	 *                        Defaults to wpdb::$blogid.
-	 * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
+	 *                        Defaults to `wpdb::$blogid`.
+	 * @return string[] 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 ) {
@@ -1065,15 +1157,15 @@
 	}
 
 	/**
-	 * Selects a database using the current database connection.
+	 * Selects a database using the current or provided database connection.
 	 *
 	 * The database name will be changed based on the current database connection.
 	 * On failure, the execution will bail and display a DB error.
 	 *
 	 * @since 0.71
 	 *
-	 * @param string        $db  MySQL database name.
-	 * @param resource|null $dbh Optional link identifier.
+	 * @param string          $db  Database name.
+	 * @param mysqli|resource $dbh Optional database connection.
 	 */
 	public function select( $db, $dbh = null ) {
 		if ( is_null( $dbh ) ) {
@@ -1090,11 +1182,11 @@
 			if ( ! did_action( 'template_redirect' ) ) {
 				wp_load_translations_early();
 
-				$message = '<h1>' . __( 'Can&#8217;t select database' ) . "</h1>\n";
+				$message = '<h1>' . __( 'Cannot select database' ) . "</h1>\n";
 
 				$message .= '<p>' . sprintf(
 					/* translators: %s: Database name. */
-					__( 'We were able to connect to the database server (which means your username and password is okay) but not able to select the %s database.' ),
+					__( 'The database server could be connected to (which means your username and password is okay) but the %s database could not be selected.' ),
 					'<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>'
 				) . "</p>\n";
 
@@ -1118,7 +1210,7 @@
 
 				$message .= '<p>' . sprintf(
 					/* translators: %s: Support forums URL. */
-					__( 'If you don&#8217;t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="%s">WordPress Support Forums</a>.' ),
+					__( 'If you do not know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="%s">WordPress Support Forums</a>.' ),
 					__( 'https://wordpress.org/support/forums/' )
 				) . "</p>\n";
 
@@ -1140,7 +1232,7 @@
 	 * @param string $string
 	 * @return string
 	 */
-	function _weak_escape( $string ) {
+	public function _weak_escape( $string ) {
 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) {
 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
 		}
@@ -1158,8 +1250,8 @@
 	 * @param string $string String to escape.
 	 * @return string Escaped string.
 	 */
-	function _real_escape( $string ) {
-		if ( ! is_scalar( $string ) && ! is_null( $string ) ) {
+	public function _real_escape( $string ) {
+		if ( ! is_scalar( $string ) ) {
 			return '';
 		}
 
@@ -1171,12 +1263,11 @@
 			}
 		} else {
 			$class = get_class( $this );
-			if ( function_exists( '__' ) ) {
-				/* translators: %s: Database access abstraction class, usually wpdb or a class extending wpdb. */
-				_doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), '3.6.0' );
-			} else {
-				_doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), '3.6.0' );
-			}
+
+			wp_load_translations_early();
+			/* translators: %s: Database access abstraction class, usually wpdb or a class extending wpdb. */
+			_doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), '3.6.0' );
+
 			$escaped = addslashes( $string );
 		}
 
@@ -1260,18 +1351,19 @@
 	 * Prepares a SQL query for safe execution.
 	 *
 	 * Uses sprintf()-like syntax. The following placeholders can be used in the query string:
-	 *   %d (integer)
-	 *   %f (float)
-	 *   %s (string)
+	 *
+	 * - %d (integer)
+	 * - %f (float)
+	 * - %s (string)
 	 *
 	 * All placeholders MUST be left unquoted in the query string. A corresponding argument
 	 * MUST be passed for each placeholder.
 	 *
 	 * Note: There is one exception to the above: for compatibility with old behavior,
-	 * numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes
+	 * numbered or formatted string placeholders (eg, `%1$s`, `%5s`) will not have quotes
 	 * added by this function, so should be passed with appropriate quotes around them.
 	 *
-	 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards
+	 * Literal percentage signs (`%`) in the query string must be written as `%%`. Percentage wildcards
 	 * (for example, to use in LIKE syntax) must be passed via a substitution argument containing
 	 * the complete LIKE string, these cannot be inserted directly in the query string.
 	 * Also see wpdb::esc_like().
@@ -1280,6 +1372,7 @@
 	 * containing all arguments. A combination of the two is not supported.
 	 *
 	 * Examples:
+	 *
 	 *     $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) );
 	 *     $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
 	 *
@@ -1320,7 +1413,7 @@
 
 		// If args were passed as an array (as in vsprintf), move them up.
 		$passed_as_array = false;
-		if ( is_array( $args[0] ) && count( $args ) === 1 ) {
+		if ( isset( $args[0] ) && is_array( $args[0] ) && 1 === count( $args ) ) {
 			$passed_as_array = true;
 			$args            = $args[0];
 		}
@@ -1420,7 +1513,7 @@
 	}
 
 	/**
-	 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
+	 * First half of escaping for `LIKE` special characters `%` and `_` before preparing for SQL.
 	 *
 	 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security.
 	 *
@@ -1609,7 +1702,7 @@
 	/**
 	 * Connects to and selects database.
 	 *
-	 * If $allow_bail is false, the lack of database connection will need to be handled manually.
+	 * If `$allow_bail` is false, the lack of database connection will need to be handled manually.
 	 *
 	 * @since 3.0.0
 	 * @since 3.9.0 $allow_bail parameter added.
@@ -1628,6 +1721,13 @@
 		$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
 
 		if ( $this->use_mysqli ) {
+			/*
+			 * Set the MySQLi error reporting off because WordPress handles its own.
+			 * This is due to the default value change from `MYSQLI_REPORT_OFF`
+			 * to `MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT` in PHP 8.1.
+			 */
+			mysqli_report( MYSQLI_REPORT_OFF );
+
 			$this->dbh = mysqli_init();
 
 			$host    = $this->dbhost;
@@ -1702,7 +1802,7 @@
 
 			$message .= '<p>' . sprintf(
 				/* translators: 1: wp-config.php, 2: Database host. */
-				__( 'This either means that the username and password information in your %1$s file is incorrect or we can&#8217;t contact the database server at %2$s. This could mean your host&#8217;s database server is down.' ),
+				__( 'This either means that the username and password information in your %1$s file is incorrect or that contact with the database server at %2$s could not be established. This could mean your host&#8217;s database server is down.' ),
 				'<code>wp-config.php</code>',
 				'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
 			) . "</p>\n";
@@ -1715,7 +1815,7 @@
 
 			$message .= '<p>' . sprintf(
 				/* translators: %s: Support forums URL. */
-				__( 'If you&#8217;re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
+				__( 'If you are unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
 				__( 'https://wordpress.org/support/forums/' )
 			) . "</p>\n";
 
@@ -1751,9 +1851,16 @@
 	 * @since 4.9.0
 	 *
 	 * @param string $host The DB_HOST setting to parse.
-	 * @return array|false Array containing the host, the port, the socket and
-	 *                     whether it is an IPv6 address, in that order.
-	 *                     False if $host couldn't be parsed.
+	 * @return array|false {
+	 *     Array containing the host, the port, the socket and
+	 *     whether it is an IPv6 address, in that order.
+	 *     False if the host couldn't be parsed.
+	 *
+	 *     @type string      $0 Host name.
+	 *     @type string|null $1 Port.
+	 *     @type string|null $2 Socket.
+	 *     @type bool        $3 Whether it is an IPv6 address.
+	 * }
 	 */
 	public function parse_db_host( $host ) {
 		$port    = null;
@@ -1801,7 +1908,7 @@
 	 * If this function is unable to reconnect, it will forcibly die, or if called
 	 * after the {@see '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.
+	 * If `$allow_bail` is false, the lack of database connection will need to be handled manually.
 	 *
 	 * @since 3.9.0
 	 *
@@ -1861,7 +1968,7 @@
 
 		$message .= '<p>' . sprintf(
 			/* translators: %s: Database host. */
-			__( 'This means that we lost contact with the database server at %s. This could mean your host&#8217;s database server is down.' ),
+			__( 'This means that the contact with the database server at %s was lost. This could mean your host&#8217;s database server is down.' ),
 			'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
 		) . "</p>\n";
 
@@ -1872,7 +1979,7 @@
 
 		$message .= '<p>' . sprintf(
 			/* translators: %s: Support forums URL. */
-			__( 'If you&#8217;re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
+			__( 'If you are unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
 			__( 'https://wordpress.org/support/forums/' )
 		) . "</p>\n";
 
@@ -1885,7 +1992,7 @@
 	}
 
 	/**
-	 * Performs a MySQL database query, using current database connection.
+	 * Performs a database query, using current database connection.
 	 *
 	 * More information can be found on the documentation page.
 	 *
@@ -1932,7 +2039,13 @@
 			// to flush again, just to make sure everything is clear.
 			$this->flush();
 			if ( $stripped_query !== $query ) {
-				$this->insert_id = 0;
+				$this->insert_id  = 0;
+				$this->last_query = $query;
+
+				wp_load_translations_early();
+
+				$this->last_error = __( 'WordPress database error: Could not perform query because it contains invalid data.' );
+
 				return false;
 			}
 		}
@@ -1944,7 +2057,7 @@
 
 		$this->_do_query( $query );
 
-		// MySQL server has gone away, try to reconnect.
+		// Database server has gone away, try to reconnect.
 		$mysql_errno = 0;
 		if ( ! empty( $this->dbh ) ) {
 			if ( $this->use_mysqli ) {
@@ -2169,6 +2282,7 @@
 	 * Inserts a row into the table.
 	 *
 	 * Examples:
+	 *
 	 *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
 	 *     wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
 	 *
@@ -2198,6 +2312,7 @@
 	 * Replaces a row in the table.
 	 *
 	 * Examples:
+	 *
 	 *     wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
 	 *     wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
 	 *
@@ -2248,7 +2363,7 @@
 	 *                             Default 'INSERT'.
 	 * @return int|false The number of rows affected, or false on error.
 	 */
-	function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
+	public function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
 		$this->insert_id = 0;
 
 		if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ), true ) ) {
@@ -2285,6 +2400,7 @@
 	 * Updates a row in the table.
 	 *
 	 * Examples:
+	 *
 	 *     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' ) )
 	 *
@@ -2364,6 +2480,7 @@
 	 * Deletes a row in the table.
 	 *
 	 * Examples:
+	 *
 	 *     wpdb::delete( 'table', array( 'ID' => 1 ) )
 	 *     wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
 	 *
@@ -2452,6 +2569,30 @@
 		$converted_data = $this->strip_invalid_text( $data );
 
 		if ( $data !== $converted_data ) {
+
+			$problem_fields = array();
+			foreach ( $data as $field => $value ) {
+				if ( $value !== $converted_data[ $field ] ) {
+					$problem_fields[] = $field;
+				}
+			}
+
+			wp_load_translations_early();
+
+			if ( 1 === count( $problem_fields ) ) {
+				$this->last_error = sprintf(
+					/* translators: %s: Database field where the error occurred. */
+					__( 'WordPress database error: Processing the value for the following field failed: %s. The supplied value may be too long or contains invalid data.' ),
+					reset( $problem_fields )
+				);
+			} else {
+				$this->last_error = sprintf(
+					/* translators: %s: Database fields where the error occurred. */
+					__( 'WordPress database error: Processing the values for the following fields failed: %s. The supplied values may be too long or contain invalid data.' ),
+					implode( ', ', $problem_fields )
+				);
+			}
+
 			return false;
 		}
 
@@ -2573,11 +2714,11 @@
 	public function get_var( $query = null, $x = 0, $y = 0 ) {
 		$this->func_call = "\$db->get_var(\"$query\", $x, $y)";
 
-		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
-			$this->check_current_query = false;
-		}
-
 		if ( $query ) {
+			if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
+				$this->check_current_query = false;
+			}
+
 			$this->query( $query );
 		}
 
@@ -2607,11 +2748,11 @@
 	public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
 		$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
 
-		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
-			$this->check_current_query = false;
-		}
-
 		if ( $query ) {
+			if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
+				$this->check_current_query = false;
+			}
+
 			$this->query( $query );
 		} else {
 			return null;
@@ -2649,11 +2790,11 @@
 	 * @return array Database query result. Array indexed from 0 by SQL result row number.
 	 */
 	public function get_col( $query = null, $x = 0 ) {
-		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
-			$this->check_current_query = false;
-		}
-
 		if ( $query ) {
+			if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
+				$this->check_current_query = false;
+			}
+
 			$this->query( $query );
 		}
 
@@ -2687,11 +2828,11 @@
 	public function get_results( $query = null, $output = OBJECT ) {
 		$this->func_call = "\$db->get_results(\"$query\", $output)";
 
-		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
-			$this->check_current_query = false;
-		}
-
 		if ( $query ) {
+			if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
+				$this->check_current_query = false;
+			}
+
 			$this->query( $query );
 		} else {
 			return null;
@@ -2749,13 +2890,14 @@
 		/**
 		 * Filters the table charset value before the DB is checked.
 		 *
-		 * Passing a non-null value to the filter will effectively short-circuit
+		 * Returning a non-null value from the filter will effectively short-circuit
 		 * checking the DB for the charset, returning that value instead.
 		 *
 		 * @since 4.2.0
 		 *
-		 * @param string|null $charset The character set to use. Default null.
-		 * @param string      $table   The name of the table being checked.
+		 * @param string|WP_Error|null $charset The character set to use, WP_Error object
+		 *                                      if it couldn't be found. Default null.
+		 * @param string               $table   The name of the table being checked.
 		 */
 		$charset = apply_filters( 'pre_get_table_charset', null, $table );
 		if ( null !== $charset ) {
@@ -2773,7 +2915,7 @@
 		$table       = '`' . implode( '`.`', $table_parts ) . '`';
 		$results     = $this->get_results( "SHOW FULL COLUMNS FROM $table" );
 		if ( ! $results ) {
-			return new WP_Error( 'wpdb_get_table_charset_failure' );
+			return new WP_Error( 'wpdb_get_table_charset_failure', __( 'Could not retrieve table charset.' ) );
 		}
 
 		foreach ( $results as $column ) {
@@ -2908,9 +3050,12 @@
 	 *
 	 * @param string $table  Table name.
 	 * @param string $column Column name.
-	 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' ).
-	 *                              False if the column has no length (for example, numeric column).
-	 *                              WP_Error object if there was an error.
+	 * @return array|false|WP_Error {
+	 *     Array of column length information, false if the column has no length (for
+	 *     example, numeric column), WP_Error object if there was an error.
+	 *
+	 *     @type int    $length The column length.
+	 *     @type string $type   One of 'byte' or 'char'.
 	 */
 	public function get_col_length( $table, $column ) {
 		$tablekey  = strtolower( $table );
@@ -3215,7 +3360,7 @@
 			$this->check_current_query = false;
 			$row                       = $this->get_row( 'SELECT ' . implode( ', ', $sql ), ARRAY_A );
 			if ( ! $row ) {
-				return new WP_Error( 'wpdb_strip_invalid_text_failure' );
+				return new WP_Error( 'wpdb_strip_invalid_text_failure', __( 'Could not strip invalid text.' ) );
 			}
 
 			foreach ( array_keys( $data ) as $column ) {
@@ -3510,7 +3655,6 @@
 		}
 	}
 
-
 	/**
 	 * Closes the current database connection.
 	 *
@@ -3656,7 +3800,7 @@
 	}
 
 	/**
-	 * Retrieves the MySQL server version.
+	 * Retrieves the database server version.
 	 *
 	 * @since 2.7.0
 	 *
@@ -3667,7 +3811,7 @@
 	}
 
 	/**
-	 * Retrieves full MySQL server information.
+	 * Retrieves full database server information.
 	 *
 	 * @since 5.5.0
 	 *