Commit 9506f4d0 authored by lucha's avatar lucha
Browse files

Update hyperdb 1.5

parent 49c79ddc
<?php
// HyperDB
// This file should be installed at ABSPATH/wp-content/db.php
/*
Plugin Name: HyperDB
Plugin URI: https://wordpress.org/plugins/hyperdb/
Description: An advanced database class that supports replication, failover, load balancing, and partitioning.
Author: Automattic
License: GPLv2 or later
Version: 1.5
*/
/** This file should be installed at ABSPATH/wp-content/db.php **/
/** Load the wpdb class while preventing instantiation **/
$wpdb = true;
......@@ -39,6 +47,9 @@ define( 'HYPERDB_LAG_OK', 1 );
define( 'HYPERDB_LAG_BEHIND', 2 );
define( 'HYPERDB_LAG_UNKNOWN', 3 );
define( 'HYPERDB_CONN_HOST_ERROR', 2003 ); // Can't connect to MySQL server on '%s' (%d)
define( 'HYPERDB_SERVER_GONE_ERROR', 2006 ); // MySQL server has gone away
class hyperdb extends wpdb {
/**
* The last table that was queried
......@@ -99,7 +110,7 @@ class hyperdb extends wpdb {
var $save_query_callback = null;
/**
* Whether to use mysql_pconnect instead of mysql_connect
* Whether to use persistent connections
* @var bool
*/
var $persistent = false;
......@@ -112,7 +123,7 @@ class hyperdb extends wpdb {
var $max_connections = 10;
/**
* Whether to check with fsockopen prior to mysql_connect.
* Whether to check with fsockopen prior to connecting to mysql.
* @var bool
*/
var $check_tcp_responsiveness = true;
......@@ -141,12 +152,6 @@ class hyperdb extends wpdb {
*/
var $open_connections = array();
/**
* Lookup array (dbhname => host:port)
* @var array
*/
var $dbh2host = array();
/**
* The last server used and the database name selected
* @var array
......@@ -173,11 +178,20 @@ class hyperdb extends wpdb {
var $default_lag_threshold = null;
/**
* Triggers __construct() for backwards compatibility with PHP4
* Lookup array (dbhname => host:port)
* @var array
*/
function hyperdb( $args = null ) {
return $this->__construct($args);
}
var $dbh2host = array();
/**
* Keeps track of the dbhname usage and errors.
*/
var $dbhname_heartbeats = array();
/**
* Counter for how many queries have failed during the life of the $wpdb object
*/
var $num_failed_queries = 0;
/**
* Gets ready to make database connections
......@@ -189,9 +203,18 @@ class hyperdb extends wpdb {
if ( isset($args[$var]) )
$this->$var = $args[$var];
$this->use_mysqli = $this->should_use_mysqli();
$this->init_charset();
}
/**
* Triggers __construct() for backwards compatibility with PHP4
*/
function hyperdb( $args = null ) {
return $this->__construct($args);
}
/**
* Sets $this->charset and $this->collate
*/
......@@ -247,11 +270,24 @@ class hyperdb extends wpdb {
* @param string query
* @return string table
*/
function get_table_from_query ( $q ) {
function get_table_from_query( $q ) {
// Remove characters that can legally trail the table name
$q = rtrim($q, ';/-#');
// allow (select...) union [...] style queries. Use the first queries table name.
$q = ltrim($q, "\t (");
// Strip everything between parentheses except nested
// selects and use only 1500 chars of the query
$q = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', substr( $q, 0, 1500 ) );
// Refer to the previous query
// wpdb doesn't implement last_table, so we run it first.
if ( preg_match('/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q) )
return $this->last_table;
if( method_exists( get_parent_class( $this ), 'get_table_from_query' ) ) {
// WPDB has added support for get_table_from_query, which should take precedence
return parent::get_table_from_query( $q );
}
// Quickly match most common queries
if ( preg_match('/^\s*(?:'
......@@ -260,18 +296,14 @@ class hyperdb extends wpdb {
. '|REPLACE(?:\s+INTO)?'
. '|UPDATE(?:\s+IGNORE)?'
. '|DELETE(?:\s+IGNORE)?(?:\s+FROM)?'
. ')\s+`?(\w+)`?/is', $q, $maybe) )
. ')\s+`?([\w-]+)`?/is', $q, $maybe) )
return $maybe[1];
// Refer to the previous query
if ( preg_match('/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q) )
return $this->last_table;
// SHOW TABLE STATUS and SHOW TABLES
if ( preg_match('/^\s*(?:'
. 'SHOW\s+TABLE\s+STATUS.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
. '|SHOW\s+(?:FULL\s+)?TABLES.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
. ')\W(\w+)\W/is', $q, $maybe) )
. ')\W([\w-]+)\W/is', $q, $maybe) )
return $maybe[1];
// Big pattern for the rest of the table-related queries in MySQL 5.0
......@@ -293,7 +325,7 @@ class hyperdb extends wpdb {
. '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
. '|(?:GRANT|REVOKE).*ON\s+TABLE'
. '|SHOW\s+(?:.*FROM|.*TABLE)'
. ')\s+`?(\w+)`?/is', $q, $maybe) )
. ')\s+`?([\w-]+)`?/is', $q, $maybe) )
return $maybe[1];
}
......@@ -305,7 +337,7 @@ class hyperdb extends wpdb {
function is_write_query( $q ) {
// Quick and dirty: only SELECT statements are considered read-only.
$q = ltrim($q, "\r\n\t (");
return !preg_match('/^(?:SELECT|SHOW|DESCRIBE|EXPLAIN)\s/i', $q);
return !preg_match('/^(?:SELECT|SHOW|DESCRIBE|DESC|EXPLAIN)\s/i', $q);
}
/**
......@@ -320,10 +352,10 @@ class hyperdb extends wpdb {
* of them returns something other than null.
*/
function run_callbacks( $group, $args = null) {
if ( !isset( $this->hyper_callbacks[ $group ] ) || !is_array( $this->hyper_callbacks[ $group ] ) )
if ( ! isset( $this->hyper_callbacks[ $group ] ) || ! is_array( $this->hyper_callbacks[ $group ] ) )
return null;
if ( !isset($args) ) {
if ( ! isset( $args ) ) {
$args = array( &$this );
} elseif ( is_array( $args ) ) {
$args[] = &$this;
......@@ -344,30 +376,6 @@ class hyperdb extends wpdb {
* @return resource mysql database connection
*/
function db_connect( $query = '' ) {
$connect_function = $this->persistent ? 'mysql_pconnect' : 'mysql_connect';
if ( empty( $this->hyper_servers ) ) {
if ( is_resource( $this->dbh ) )
return $this->dbh;
if (
!defined('DB_HOST')
|| !defined('DB_USER')
|| !defined('DB_PASSWORD')
|| !defined('DB_NAME') )
return $this->bail("We were unable to query because there was no database defined.");
$this->dbh = @ $connect_function(DB_HOST, DB_USER, DB_PASSWORD, true);
if ( ! is_resource( $this->dbh ) )
return $this->bail("We were unable to connect to the database. (DB_HOST)");
if ( ! mysql_select_db(DB_NAME, $this->dbh) )
return $this->bail("We were unable to select the database.");
if ( ! empty( $this->charset ) ) {
$collation_query = "SET NAMES '$this->charset'";
if ( !empty( $this->collate ) )
$collation_query .= " COLLATE '$this->collate'";
mysql_query($collation_query, $this->dbh);
}
return $this->dbh;
}
if ( empty( $query ) )
return false;
......@@ -383,14 +391,39 @@ class hyperdb extends wpdb {
$dataset = $this->callback_result;
}
if ( !isset($dataset) )
if ( ! isset($dataset) )
$dataset = 'global';
if ( !$dataset )
return $this->bail("Unable to determine which dataset to query. ($this->table)");
if ( ! $dataset )
return $this->log_and_bail("Unable to determine dataset (for table: $this->table)");
else
$this->dataset = $dataset;
$this->run_callbacks( 'dataset_found', $dataset );
if ( empty( $this->hyper_servers ) ) {
if ( $this->is_mysql_connection( $this->dbh ) )
return $this->dbh;
if (
!defined('DB_HOST')
|| !defined('DB_USER')
|| !defined('DB_PASSWORD')
|| !defined('DB_NAME') )
return $this->log_and_bail("We were unable to query because there was no database defined");
$this->dbh = $this->ex_mysql_connect( DB_HOST, DB_USER, DB_PASSWORD, $this->persistent );
if ( ! $this->is_mysql_connection( $this->dbh ) )
return $this->log_and_bail("We were unable to connect to the database. (DB_HOST)");
if ( ! $this->ex_mysql_select_db( DB_NAME, $this->dbh ) )
return $this->log_and_bail("We were unable to select the database");
if ( ! empty( $this->charset ) ) {
$collation_query = "SET NAMES '$this->charset'";
if ( !empty( $this->collate ) )
$collation_query .= " COLLATE '$this->collate'";
$this->ex_mysql_query( $collation_query, $this->dbh );
}
return $this->dbh;
}
// Determine whether the query must be sent to the master (a writable server)
if ( !empty( $use_master ) || $this->srtm === true || isset($this->srtm[$this->table]) ) {
$use_master = true;
......@@ -421,7 +454,7 @@ class hyperdb extends wpdb {
}
// Try to reuse an existing connection
while ( isset( $this->dbhs[$dbhname] ) && is_resource( $this->dbhs[$dbhname] ) ) {
while ( isset( $this->dbhs[$dbhname] ) && $this->is_mysql_connection( $this->dbhs[$dbhname] ) ) {
// Find the connection for incrementing counters
foreach ( array_keys($this->db_connections) as $i )
if ( $this->db_connections[$i]['dbhname'] == $dbhname )
......@@ -431,7 +464,7 @@ class hyperdb extends wpdb {
$name = $server['name'];
// A callback has specified a database name so it's possible the existing connection selected a different one.
if ( $name != $this->used_servers[$dbhname]['name'] ) {
if ( !mysql_select_db($name, $this->dbhs[$dbhname]) ) {
if ( ! $this->ex_mysql_select_db( $name, $this->dbhs[$dbhname] ) ) {
// this can happen when the user varies and lacks permission on the $name database
if ( isset( $conn['disconnect (select failed)'] ) )
++$conn['disconnect (select failed)'];
......@@ -458,7 +491,7 @@ class hyperdb extends wpdb {
$this->last_used_server = $this->used_servers[$dbhname];
$this->last_connection = compact('dbhname', 'name');
if ( !mysql_ping($this->dbhs[$dbhname]) ) {
if ( $this->should_mysql_ping() && ! $this->ex_mysql_ping( $this->dbhs[$dbhname] ) ) {
if ( isset( $conn['disconnect (ping failed)'] ) )
++$conn['disconnect (ping failed)'];
else
......@@ -481,7 +514,7 @@ class hyperdb extends wpdb {
}
if ( empty($this->hyper_servers[$dataset][$operation]) )
return $this->bail("No databases available with $this->table ($dataset)");
return $this->log_and_bail("No databases available with $this->table ($dataset)");
// Put the groups in order by priority
ksort($this->hyper_servers[$dataset][$operation]);
......@@ -497,7 +530,7 @@ class hyperdb extends wpdb {
}
if ( !$tries_remaining = count( $servers ) )
return $this->bail("No database servers were found to match the query. ($this->table, $dataset)");
return $this->log_and_bail("No database servers were found to match the query ($this->table, $dataset)");
if ( !isset( $unique_servers ) )
$unique_servers = $tries_remaining;
......@@ -519,7 +552,7 @@ class hyperdb extends wpdb {
// $group, $key
extract($group_key, EXTR_OVERWRITE);
// $host, $user, $password, $name, $read, $write [, $lag_threshold, $connect_function, $timeout ]
// $host, $user, $password, $name, $read, $write [, $lag_threshold, $timeout ]
extract($this->hyper_servers[$dataset][$operation][$group][$key], EXTR_OVERWRITE);
$port = null;
......@@ -571,18 +604,20 @@ class hyperdb extends wpdb {
$this->timer_start();
// Connect if necessary or possible
$tcp = null;
if ( $use_master || !$tries_remaining || !$this->check_tcp_responsiveness
|| true === $tcp = $this->check_tcp_responsiveness($host, $port, $timeout) )
$server_state = null;
if ( $use_master || ! $tries_remaining ||
'up' == $server_state = $this->get_server_state( $host, $port, $timeout ) )
{
$this->dbhs[$dbhname] = @ $connect_function( "$host:$port", $user, $password, true );
$this->set_connect_timeout( 'pre_connect', $use_master, $tries_remaining );
$this->dbhs[$dbhname] = $this->ex_mysql_connect( "$host:$port", $user, $password, $this->persistent );
$this->set_connect_timeout( 'post_connect', $use_master, $tries_remaining );
} else {
$this->dbhs[$dbhname] = false;
}
$elapsed = $this->timer_stop();
if ( is_resource( $this->dbhs[$dbhname] ) ) {
if ( $this->is_mysql_connection( $this->dbhs[$dbhname] ) ) {
/**
* If we care about lag, disconnect lagged slaves and try to find others.
* We don't disconnect if it is the last lagged slave and it is with the best preference.
......@@ -604,7 +639,7 @@ class hyperdb extends wpdb {
$msg = "Replication lag of {$this->lag}s on $host:$port ($dbhname)";
$this->print_error( $msg );
continue;
} elseif ( mysql_select_db( $name, $this->dbhs[ $dbhname ] ) ) {
} elseif ( $this->ex_mysql_select_db( $name, $this->dbhs[$dbhname] ) ) {
$success = true;
$this->current_host = "$host:$port";
$this->dbh2host[$dbhname] = "$host:$port";
......@@ -617,6 +652,16 @@ class hyperdb extends wpdb {
}
}
if ( 'down' == $server_state )
continue; // don't flood the logs if already down
if ( HYPERDB_CONN_HOST_ERROR == $this->ex_mysql_errno() &&
( 'up' == $server_state || ! $tries_remaining ) )
{
$this->mark_server_as_down( $host, $port );
$server_state = 'down';
}
$success = false;
$this->last_connection = compact('dbhname', 'host', 'port', 'user', 'name', 'tcp', 'elapsed', 'success');
$this->db_connections[] = $this->last_connection;
......@@ -624,15 +669,15 @@ class hyperdb extends wpdb {
$msg .= "'referrer' => '{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}',\n";
$msg .= "'server' => {$server},\n";
$msg .= "'host' => {$host},\n";
$msg .= "'error' => " . mysql_error() . ",\n";
$msg .= "'errno' => " . mysql_errno() . ",\n";
$msg .= "'tcp_responsive' => " . ( $tcp === true ? 'true' : $tcp ) . ",\n";
$msg .= "'error' => " . $this->ex_mysql_error() . ",\n";
$msg .= "'errno' => " . $this->ex_mysql_errno() . ",\n";
$msg .= "'server_state' => $server_state\n";
$msg .= "'lagged_status' => " . ( isset( $lagged_status ) ? $lagged_status : HYPERDB_LAG_UNKNOWN );
$this->print_error( $msg );
}
if ( !$success || !isset($this->dbhs[$dbhname]) || !is_resource( $this->dbhs[$dbhname] ) ) {
if ( ! $success || ! isset( $this->dbhs[$dbhname] ) || ! $this->is_mysql_connection( $this->dbhs[$dbhname] ) ) {
if ( !isset( $ignore_slave_lag ) && count( $unique_lagged_slaves ) ) {
// Lagged slaves were not used. Ignore the lag for this connection attempt and retry.
$ignore_slave_lag = true;
......@@ -681,7 +726,7 @@ class hyperdb extends wpdb {
/**
* Sets the connection's character set.
* @param resource $dbh The resource given by mysql_connect
* @param resource $dbh The resource given by ex_mysql_connect
* @param string $charset The character set (optional)
* @param string $collate The collation (optional)
*/
......@@ -690,29 +735,52 @@ class hyperdb extends wpdb {
$charset = $this->charset;
if ( !isset($collate) )
$collate = $this->collate;
if ( $this->has_cap( 'collation', $dbh ) && !empty( $charset ) ) {
if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset', $dbh ) ) {
mysql_set_charset( $charset, $dbh );
if ( ! $this->has_cap( 'collation', $dbh ) || empty( $charset ) )
return;
if ( ! in_array( strtolower( $charset ), array( 'utf8', 'utf8mb4', 'latin1' ) ) )
wp_die( "$charset charset isn't supported in HyperDB for security reasons" );
if ( $this->is_mysql_set_charset_callable() && $this->has_cap( 'set_charset', $dbh ) ) {
$this->ex_mysql_set_charset( $charset, $dbh );
$this->real_escape = true;
} else {
$query = $this->prepare( 'SET NAMES %s', $charset );
if ( ! empty( $collate ) )
$query .= $this->prepare( ' COLLATE %s', $collate );
mysql_query( $query, $dbh );
}
$this->ex_mysql_query( $query, $dbh );
}
}
/*
* Force addslashes() for the escapes.
*
* HyperDB makes connections when a query is made
* which is why we can't use mysql_real_escape_string() for escapes.
* This is also the reason why we don't allow certain charsets. See set_charset().
*/
function _real_escape( $string ) {
$escaped = addslashes( $string );
if ( method_exists( get_parent_class( $this ), 'add_placeholder_escape' ) ) {
$escaped = $this->add_placeholder_escape( $escaped );
}
return $escaped;
}
/**
* Disconnect and remove connection from open connections list
* @param string $tdbhname
*/
function disconnect($dbhname) {
if ( $k = array_search($dbhname, $this->open_connections) )
if ( false !== $k = array_search($dbhname, $this->open_connections) )
unset($this->open_connections[$k]);
if ( is_resource($this->dbhs[$dbhname]) )
mysql_close($this->dbhs[$dbhname]);
foreach ( array_keys( $this->db_connections ) as $i )
if ( $this->db_connections[$i]['dbhname'] == $dbhname )
unset( $this->db_connections[$i] );
if ( $this->is_mysql_connection( $this->dbhs[$dbhname] ) )
$this->ex_mysql_close( $this->dbhs[$dbhname] );
unset($this->dbhs[$dbhname]);
}
......@@ -722,6 +790,7 @@ class hyperdb extends wpdb {
*/
function flush() {
$this->last_error = '';
$this->last_errno = 0;
$this->num_rows = 0;
parent::flush();
}
......@@ -731,7 +800,7 @@ class hyperdb extends wpdb {
* @param string $query
* @return int number of rows
*/
function query($query) {
function query( $query ) {
// 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);
......@@ -746,24 +815,67 @@ class hyperdb extends wpdb {
// Keep track of the last query for debug..
$this->last_query = $query;
if ( preg_match('/^\s*SELECT\s+FOUND_ROWS(\s*)/i', $query) && is_resource($this->last_found_rows_result) ) {
if ( preg_match( '/^\s*SELECT\s+FOUND_ROWS(\s*)/i', $query ) ) {
if ( $this->is_mysql_result( $this->last_found_rows_result ) ) {
$this->result = $this->last_found_rows_result;
$elapsed = 0;
} else {
$this->print_error( "Attempted SELECT FOUND_ROWS() without prior SQL_CALC_FOUND_ROWS." );
return false;
}
} else {
$this->dbh = $this->db_connect( $query );
if ( ! is_resource($this->dbh) )
if ( ! $this->is_mysql_connection( $this->dbh ) ) {
$this->check_current_query = true;
$this->last_error = 'Database connection failed';
$this->num_failed_queries++;
do_action( 'sql_query_log', $query, false, $this->last_error );
return false;
}
$query_comment = $this->run_callbacks( 'get_query_comment', $query );
if ( ! empty( $query_comment ) )
$query = rtrim( $query, ";\t \n\r" ) . ' /* ' . $query_comment . ' */';
// If we're writing to the database, make sure the query will write safely.
if ( $this->check_current_query && method_exists( $this, 'check_ascii' ) && ! $this->check_ascii( $query ) ) {
$stripped_query = $this->strip_invalid_text_from_query( $query );
if ( $stripped_query !== $query ) {
$this->insert_id = 0;
$this->last_error = 'Invalid query';
$this->num_failed_queries++;
do_action( 'sql_query_log', $query, false, $this->last_error );
return false;
}
}
$this->check_current_query = true;
// Inject setup and teardown statements
$statement_before_query = $this->run_callbacks( 'statement_before_query' );
$statement_after_query = $this->run_callbacks( 'statement_after_query' );
$query_for_log = $query;
$this->timer_start();
$this->result = mysql_query($query, $this->dbh);
if ( $statement_before_query ) {
$query_for_log = "$statement_before_query; $query_for_log";
$this->ex_mysql_query( $statement_before_query, $this->dbh );
}
$this->result = $this->ex_mysql_query( $query, $this->dbh );
if ( $statement_after_query ) {
$query_for_log = "$query_for_log; $statement_after_query";
$this->ex_mysql_query( $statement_after_query, $this->dbh );
}
$elapsed = $this->timer_stop();
++$this->num_queries;
if ( preg_match('/^\s*SELECT\s+SQL_CALC_FOUND_ROWS\s/i', $query) ) {
if ( false === strpos($query, "NO_SELECT_FOUND_ROWS") ) {
$this->timer_start();
$this->last_found_rows_result = mysql_query("SELECT FOUND_ROWS()", $this->dbh);
$this->last_found_rows_result = $this->ex_mysql_query( "SELECT FOUND_ROWS()", $this->dbh );
$elapsed += $this->timer_stop();
++$this->num_queries;
$query .= "; SELECT FOUND_ROWS()";
......@@ -772,44 +884,58 @@ class hyperdb extends wpdb {
$this->last_found_rows_result = null;
}
$this->dbhname_heartbeats[$this->dbhname]['last_used'] = microtime( true );
if ( $this->save_queries ) {
if ( is_callable($this->save_query_callback) )
$this->queries[] = call_user_func_array( $this->save_query_callback, array( $query, $elapsed, $this->save_backtrace ? debug_backtrace( false ) : null, &$this ) );
else
$this->queries[] = array( $query, $elapsed, $this->get_caller() );
if ( is_callable($this->save_query_callback) ) {
$saved_query = call_user_func_array( $this->save_query_callback, array( $query_for_log, $elapsed, $this->save_backtrace ? debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ) : null, &$this ) );
if ( $saved_query !== null ) {
$this->queries[] = $saved_query;
}
} else {
$this->queries[] = array( $query_for_log, $elapsed, $this->get_caller() );
}
}
}
// If there is an error then take note of it
if ( $this->last_error = mysql_error($this->dbh) ) {
if ( $this->last_error = $this->ex_mysql_error( $this->dbh ) ) {
$this->last_errno = $this->ex_mysql_errno( $this->dbh );
$this->dbhname_heartbeats[$this->dbhname]['last_errno'] = $this->last_errno;
$this->print_error($this->last_error);
$this->num_failed_queries++;
do_action( 'sql_query_log', $query, false, $this->last_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*(insert|delete|update|replace|alter)\s/i',$query) ) {
$this->rows_affected = $this->ex_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) ) {
$this->insert_id = $this->ex_mysql_insert_id( $this->dbh );
}
// Return number of rows affected
$return_val = $this->rows_affected;
} else if ( is_bool( $this->result ) ) {
$return_val = $this->result;
$this->result = null;
} else {
$i = 0;
$this->col_info = array();
while ($i < @mysql_num_fields($this->result)) {
$this->col_info[$i] = @mysql_fetch_field($this->result);
while ( $i < $this->ex_mysql_num_fields( $this->result ) ) {
$this->col_info[$i] = $this->ex_mysql_fetch_field( $this->result );
$i++;
}
$num_rows = 0;
$this->last_result = array();
while ( $row = @mysql_fetch_object($this->result) ) {
while ( $row = $this->ex_mysql_fetch_object( $this->result ) ) {
$this->last_result[$num_rows] = $row;
$num_rows++;
}
@mysql_free_result($this->result);
$this->ex_mysql_free_result( $this->result );
$this->result = null;
// Log number of rows the query returned
$this->num_rows = $num_rows;
......@@ -818,6 +944,7 @@ class hyperdb extends wpdb {
$return_val = $this->num_rows;
}
do_action( 'sql_query_log', $query, $return_val, $this->last_error );
return $return_val;
}
......@@ -878,13 +1005,13 @@ class hyperdb extends wpdb {
function db_version( $dbh_or_table = false ) {
if ( !$dbh_or_table && $this->dbh )
$dbh =& $this->dbh;
elseif ( is_resource( $dbh_or_table ) )
elseif ( $this->is_mysql_connection( $dbh_or_table ) )
$dbh =& $dbh_or_table;
else
$dbh = $this->db_connect( "SELECT FROM $dbh_or_table $this->users" );
if ( $dbh )
return preg_replace('/[^0-9.].*/', '', mysql_get_server_info( $dbh ));
return preg_replace( '/[^0-9.].*/', '', $this->ex_mysql_get_server_info( $dbh ) );
return false;
}