Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ai
noblogs-wp
Commits
9506f4d0
Commit
9506f4d0
authored
Nov 30, 2017
by
lucha
Browse files
Update hyperdb 1.5
parent
49c79ddc
Changes
1
Hide whitespace changes
Inline
Side-by-side
wp-content/db.php
View file @
9506f4d0
<?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
;
...
...
@@ -33,12 +41,15 @@ if ( defined('DB_CONFIG_FILE') && file_exists( DB_CONFIG_FILE ) ) {
}
/**
* Common definitions
* Common definitions
*/
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
connect
ions
* @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 connect
ing 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
*/
...
...
@@ -235,7 +258,7 @@ class hyperdb extends wpdb {
/**
* Add a callback to a group of callbacks.
* The default group is 'dataset', used to examine
* The default group is 'dataset', used to examine
* queries and determine dataset.
*/
function
add_callback
(
$callback
,
$group
=
'dataset'
)
{
...
...
@@ -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
...
...
@@ -468,7 +501,7 @@ class hyperdb extends wpdb {
break
;
}
if
(
isset
(
$conn
[
'queries'
]
)
)
if
(
isset
(
$conn
[
'queries'
]
)
)
++
$conn
[
'queries'
];
else
$conn
[
'queries'
]
=
1
;
...
...
@@ -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
]);
...
...
@@ -492,13 +525,13 @@ class hyperdb extends wpdb {
foreach
(
$this
->
hyper_servers
[
$dataset
][
$operation
]
as
$group
=>
$items
)
{
$keys
=
array_keys
(
$items
);
shuffle
(
$keys
);
foreach
(
$keys
as
$key
)
foreach
(
$keys
as
$key
)
$servers
[]
=
compact
(
'group'
,
'key'
);
}
if
(
!
$tries_remaining
=
count
(
$servers
)
)
return
$this
->
bail
(
"No database servers were found to match the query
.
(
$this->table
,
$dataset
)"
);
if
(
!
$tries_remaining
=
count
(
$servers
)
)
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
;
...
...
@@ -510,8 +543,8 @@ class hyperdb extends wpdb {
$success
=
false
;
foreach
(
$servers
as
$group_key
)
{
--
$tries_remaining
;
--
$tries_remaining
;
// If all servers are lagged, we need to start ignoring the lag and retry
if
(
count
(
$unique_lagged_slaves
)
==
$unique_servers
)
break
;
...
...
@@ -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,16 +669,16 @@ 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
(
!
isset
(
$ignore_slave_lag
)
&&
count
(
$unique_lagged_slaves
)
)
{
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
;
$tries_remaining
=
count
(
$servers
);
...
...
@@ -656,7 +701,7 @@ class hyperdb extends wpdb {
break
;
}
while
(
true
);
if
(
!
isset
(
$charset
)
)
if
(
!
isset
(
$charset
)
)
$charset
=
null
;
if
(
!
isset
(
$collate
)
)
...
...
@@ -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
);
$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
);
}
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
);
$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
)
)
{
$this
->
result
=
$this
->
last_found_rows_result
;
$elapsed
=
0
;
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
)
)
{