Commit b0d15b92 by Scott

Remove unreachable code from qa-db.php

Plus add deprecation notices.
parent 81dc9e36
...@@ -35,9 +35,9 @@ function qa_db_increment_views($postid) ...@@ -35,9 +35,9 @@ function qa_db_increment_views($postid)
$query = 'UPDATE ^posts SET views=views+1, lastviewip=UNHEX($) WHERE postid=# AND (lastviewip IS NULL OR lastviewip!=UNHEX($))'; $query = 'UPDATE ^posts SET views=views+1, lastviewip=UNHEX($) WHERE postid=# AND (lastviewip IS NULL OR lastviewip!=UNHEX($))';
$ipHex = bin2hex(@inet_pton(qa_remote_ip_address())); $ipHex = bin2hex(@inet_pton(qa_remote_ip_address()));
qa_db_query_sub($query, $ipHex, $postid, $ipHex); $result = qa_db_query_sub($query, $ipHex, $postid, $ipHex);
return qa_db_affected_rows() > 0; return $result->affectedRows() > 0;
} }
......
...@@ -206,9 +206,9 @@ function qa_db_points_update_ifuser($userid, $columns) ...@@ -206,9 +206,9 @@ function qa_db_points_update_ifuser($userid, $columns)
'ON DUPLICATE KEY UPDATE ' . $updates . 'points=' . $updatepoints . '+bonus'; 'ON DUPLICATE KEY UPDATE ' . $updates . 'points=' . $updatepoints . '+bonus';
// build like this so that a #, $ or ^ character in the $userid (if external integration) isn't substituted // build like this so that a #, $ or ^ character in the $userid (if external integration) isn't substituted
qa_db_query_raw(str_replace('~', "='" . qa_db_escape_string($userid) . "'", qa_db_apply_sub($query, array($userid)))); $result = qa_db_query_raw(str_replace('~', "='" . qa_db_escape_string($userid) . "'", qa_db_apply_sub($query, array($userid))));
if (qa_db_insert_on_duplicate_inserted()) { if ($result->affectedRows() > 0) {
qa_db_userpointscount_update(); qa_db_userpointscount_update();
} }
} }
......
...@@ -1901,7 +1901,7 @@ function qa_opt($name, $value = null) ...@@ -1901,7 +1901,7 @@ function qa_opt($name, $value = null)
*/ */
function qa_debug($var) function qa_debug($var)
{ {
echo "\n" . '<pre style="padding: 10px; background-color: #eee; color: #444; font-size: 11px; text-align: left">'; echo "\n" . '<pre style="padding: 10px; background-color: #eee; color: #444; font-size: 12px; text-align: left; white-space: pre-wrap">';
echo $var === null ? 'NULL' : htmlspecialchars(print_r($var, true), ENT_COMPAT|ENT_SUBSTITUTE); echo $var === null ? 'NULL' : htmlspecialchars(print_r($var, true), ENT_COMPAT|ENT_SUBSTITUTE);
echo '</pre>' . "\n"; echo '</pre>' . "\n";
} }
......
...@@ -28,24 +28,20 @@ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly ...@@ -28,24 +28,20 @@ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly
/** /**
* Indicates to the Q2A database layer that database connections are permitted fro this point forwards * Indicates to the Q2A database layer that database connections are permitted fro this point forwards
* (before this point, some plugins may not have had a chance to override some database access functions). * (before this point, some plugins may not have had a chance to override some database access functions).
* @deprecated 1.9.0 Use DbConnection->allowConnect() instead.
*/ */
function qa_db_allow_connect() function qa_db_allow_connect()
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_service('database')->allowConnect(); qa_service('database')->allowConnect();
return;
global $qa_db_allow_connect;
$qa_db_allow_connect = true;
} }
/** /**
* Connect to the Q2A database, select the right database, optionally install the $failhandler (and call it if necessary). * Connect to the Q2A database, select the right database, optionally install the $failhandler (and call it if necessary).
* Uses mysqli as of Q2A 1.7. * Uses mysqli as of Q2A 1.7.
* @deprecated 1.9.0 Use DbConnection->connect() instead.
* @param null $failhandler * @param null $failhandler
* @return mixed|void * @return mixed|void
*/ */
...@@ -54,62 +50,12 @@ function qa_db_connect($failhandler = null) ...@@ -54,62 +50,12 @@ function qa_db_connect($failhandler = null)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_service('database')->connect($failhandler); qa_service('database')->connect($failhandler);
return;
global $qa_db_connection, $qa_db_fail_handler, $qa_db_allow_connect;
if (!$qa_db_allow_connect)
qa_fatal_error('It appears that a plugin is trying to access the database, but this is not allowed until Q2A initialization is complete.');
if (isset($failhandler))
$qa_db_fail_handler = $failhandler; // set this even if connection already opened
if ($qa_db_connection instanceof mysqli)
return;
$host = QA_FINAL_MYSQL_HOSTNAME;
$port = null;
if (defined('QA_FINAL_WORDPRESS_INTEGRATE_PATH')) {
// Wordpress allows setting port inside DB_HOST constant, like 127.0.0.1:3306
$host_and_port = explode(':', $host);
if (count($host_and_port) >= 2) {
$host = $host_and_port[0];
$port = $host_and_port[1];
}
} elseif (defined('QA_FINAL_MYSQL_PORT')) {
$port = QA_FINAL_MYSQL_PORT;
}
if (QA_PERSISTENT_CONN_DB)
$host = 'p:' . $host;
// in mysqli we connect and select database in constructor
if ($port !== null)
$db = new mysqli($host, QA_FINAL_MYSQL_USERNAME, QA_FINAL_MYSQL_PASSWORD, QA_FINAL_MYSQL_DATABASE, $port);
else
$db = new mysqli($host, QA_FINAL_MYSQL_USERNAME, QA_FINAL_MYSQL_PASSWORD, QA_FINAL_MYSQL_DATABASE);
// must use procedural `mysqli_connect_error` here prior to 5.2.9
$conn_error = mysqli_connect_error();
if ($conn_error)
qa_db_fail_error('connect', $db->connect_errno, $conn_error);
// From Q2A 1.5, we explicitly set the character encoding of the MySQL connection, instead of using lots of "SELECT BINARY col"-style queries.
// Testing showed that overhead is minimal, so this seems worth trading off against the benefit of more straightforward queries, especially
// for plugin developers.
if (!$db->set_charset('utf8'))
qa_db_fail_error('set_charset', $db->errno, $db->error);
qa_report_process_stage('db_connected');
$qa_db_connection = $db;
} }
/** /**
* If a DB error occurs, call the installed fail handler (if any) otherwise report error and exit immediately. * If a DB error occurs, call the installed fail handler (if any) otherwise report error and exit immediately.
* @deprecated 1.9.0 Use DbConnection->failError() instead.
* @param $type * @param $type
* @param int $errno * @param int $errno
* @param string $error * @param string $error
...@@ -121,27 +67,12 @@ function qa_db_fail_error($type, $errno = null, $error = null, $query = null) ...@@ -121,27 +67,12 @@ function qa_db_fail_error($type, $errno = null, $error = null, $query = null)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_service('database')->failError($type, $errno, $error, $query); qa_service('database')->failError($type, $errno, $error, $query);
return;
global $qa_db_fail_handler;
@error_log('PHP Question2Answer MySQL ' . $type . ' error ' . $errno . ': ' . $error . (isset($query) ? (' - Query: ' . $query) : ''));
if (function_exists($qa_db_fail_handler))
$qa_db_fail_handler($type, $errno, $error, $query);
else {
echo sprintf(
'<hr><div style="color: red">Database %s<p>%s</p><code>%s</code></div>',
htmlspecialchars($type . ' error ' . $errno), nl2br(htmlspecialchars($error)), nl2br(htmlspecialchars($query))
);
qa_exit('error');
}
} }
/** /**
* Return the current connection to the Q2A database, connecting if necessary and $connect is true. * Return the current connection to the Q2A database, connecting if necessary and $connect is true.
* @deprecated 1.9.0
* @param bool $connect * @param bool $connect
* @return mixed * @return mixed
*/ */
...@@ -150,50 +81,25 @@ function qa_db_connection($connect = true) ...@@ -150,50 +81,25 @@ function qa_db_connection($connect = true)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_service('database'); return qa_service('database');
global $qa_db_connection;
if ($connect && !($qa_db_connection instanceof mysqli)) {
qa_db_connect();
if (!($qa_db_connection instanceof mysqli))
qa_fatal_error('Failed to connect to database');
}
return $qa_db_connection;
} }
/** /**
* Disconnect from the Q2A database. * Disconnect from the Q2A database.
* @deprecated 1.9.0 Use DbConnection->disconnect() instead.
*/ */
function qa_db_disconnect() function qa_db_disconnect()
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_service('database')->disconnect(); qa_service('database')->disconnect();
return;
global $qa_db_connection;
if ($qa_db_connection instanceof mysqli) {
qa_report_process_stage('db_disconnect');
if (!QA_PERSISTENT_CONN_DB) {
if (!$qa_db_connection->close())
qa_fatal_error('Database disconnect failed');
}
$qa_db_connection = null;
}
} }
/** /**
* Run the raw $query, call the global failure handler if necessary, otherwise return the result resource. * Run the raw $query, call the global failure handler if necessary, otherwise return the result resource.
* If appropriate, also track the resources used by database queries, and the queries themselves, for performance debugging. * If appropriate, also track the resources used by database queries, and the queries themselves, for performance debugging.
* @deprecated 1.9.0 Use DbConnection->query() instead.
* @param $query * @param $query
* @return mixed * @return mixed
*/ */
...@@ -202,40 +108,12 @@ function qa_db_query_raw($query) ...@@ -202,40 +108,12 @@ function qa_db_query_raw($query)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_service('database')->query($query); return qa_service('database')->query($query);
if (QA_DEBUG_PERFORMANCE) {
global $qa_usage;
// time the query
$oldtime = array_sum(explode(' ', microtime()));
$result = qa_db_query_execute($query);
$usedtime = array_sum(explode(' ', microtime())) - $oldtime;
// fetch counts
$gotrows = $gotcolumns = null;
if ($result instanceof mysqli_result) {
$gotrows = $result->num_rows;
$gotcolumns = $result->field_count;
}
$qa_usage->logDatabaseQuery($query, $usedtime, $gotrows, $gotcolumns);
} else
$result = qa_db_query_execute($query);
// @error_log('Question2Answer MySQL query: '.$query);
if ($result === false) {
$db = qa_db_connection();
qa_db_fail_error('query', $db->errno, $db->error, $query);
}
return $result;
} }
/** /**
* Lower-level function to execute a query, which automatically retries if there is a MySQL deadlock error. * Lower-level function to execute a query, which automatically retries if there is a MySQL deadlock error.
* @deprecated 1.9.0 Use DbConnection->query() instead.
* @param $query * @param $query
* @return mixed * @return mixed
*/ */
...@@ -244,25 +122,12 @@ function qa_db_query_execute($query) ...@@ -244,25 +122,12 @@ function qa_db_query_execute($query)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_service('database')->query($query); return qa_service('database')->query($query);
$db = qa_db_connection();
for ($attempt = 0; $attempt < 100; $attempt++) {
$result = $db->query($query);
if ($result === false && $db->errno == 1213)
usleep(10000); // deal with InnoDB deadlock errors by waiting 0.01s then retrying
else
break;
}
return $result;
} }
/** /**
* Return $string escaped for use in queries to the Q2A database (to which a connection must have been made). * Return $string escaped for use in queries to the Q2A database (to which a connection must have been made).
* @deprecated 1.9.0 No longer needed: parameters passed to DbConnection->query() are automatically escaped.
* @param $string * @param $string
* @return mixed * @return mixed
*/ */
...@@ -272,16 +137,13 @@ function qa_db_escape_string($string) ...@@ -272,16 +137,13 @@ function qa_db_escape_string($string)
$pdo = qa_service('database')->getPDO(); $pdo = qa_service('database')->getPDO();
return $pdo->quote($string); return $pdo->quote($string);
$db = qa_db_connection();
return $db->real_escape_string($string);
} }
/** /**
* Return $argument escaped for MySQL. Add quotes around it if $alwaysquote is true or it's not numeric. * Return $argument escaped for MySQL. Add quotes around it if $alwaysquote is true or it's not numeric.
* If $argument is an array, return a comma-separated list of escaped elements, with or without $arraybrackets. * If $argument is an array, return a comma-separated list of escaped elements, with or without $arraybrackets.
* @deprecated 1.9.0
* @param $argument * @param $argument
* @param $alwaysquote * @param $alwaysquote
* @param bool $arraybrackets * @param bool $arraybrackets
...@@ -312,6 +174,7 @@ function qa_db_argument_to_mysql($argument, $alwaysquote, $arraybrackets = false ...@@ -312,6 +174,7 @@ function qa_db_argument_to_mysql($argument, $alwaysquote, $arraybrackets = false
/** /**
* Return the full name (with prefix) of database table $rawname, usually if it used after a ^ symbol. * Return the full name (with prefix) of database table $rawname, usually if it used after a ^ symbol.
* @deprecated 1.9.0 Use DbConnection->addTablePrefix() instead.
* @param $rawname * @param $rawname
* @return string * @return string
*/ */
...@@ -320,33 +183,12 @@ function qa_db_add_table_prefix($rawname) ...@@ -320,33 +183,12 @@ function qa_db_add_table_prefix($rawname)
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_service('database')->addTablePrefix($rawname); return qa_service('database')->addTablePrefix($rawname);
$prefix = QA_MYSQL_TABLE_PREFIX;
if (defined('QA_MYSQL_USERS_PREFIX')) {
switch (strtolower($rawname)) {
case 'users':
case 'userlogins':
case 'userprofile':
case 'userfields':
case 'messages':
case 'cookies':
case 'blobs':
case 'cache':
case 'userlogins_ibfk_1': // also special cases for constraint names
case 'userprofile_ibfk_1':
$prefix = QA_MYSQL_USERS_PREFIX;
break;
}
}
return $prefix . $rawname;
} }
/** /**
* Callback function to add table prefixes, as used in qa_db_apply_sub(). * Callback function to add table prefixes, as used in qa_db_apply_sub().
* @deprecated 1.9.0 No longer needed.
* @param $matches * @param $matches
* @return string * @return string
*/ */
...@@ -362,13 +204,14 @@ function qa_db_prefix_callback($matches) ...@@ -362,13 +204,14 @@ function qa_db_prefix_callback($matches)
* it is converted recursively into comma-separated list). Each element in $arguments is escaped. * it is converted recursively into comma-separated list). Each element in $arguments is escaped.
* $ is replaced by the argument in quotes (even if it's a number), # only adds quotes if the argument is non-numeric. * $ is replaced by the argument in quotes (even if it's a number), # only adds quotes if the argument is non-numeric.
* It's important to use $ when matching a textual column since MySQL won't use indexes to compare text against numbers. * It's important to use $ when matching a textual column since MySQL won't use indexes to compare text against numbers.
* @deprecated 1.9.0 Use DbConnection->applyTableSub() instead.
* @param $query * @param $query
* @param $arguments * @param $arguments
* @return mixed * @return mixed
*/ */
function qa_db_apply_sub($query, $arguments) function qa_db_apply_sub($query, $arguments)
{ {
// function left intact as it does not use db connection, and DbConnection does not allow #/$ params // function left intact as some code calls this (or qa_db_query_sub) directly
$query = preg_replace_callback('/\^([A-Za-z_0-9]+)/', 'qa_db_prefix_callback', $query); $query = preg_replace_callback('/\^([A-Za-z_0-9]+)/', 'qa_db_prefix_callback', $query);
...@@ -404,6 +247,7 @@ function qa_db_apply_sub($query, $arguments) ...@@ -404,6 +247,7 @@ function qa_db_apply_sub($query, $arguments)
/** /**
* Run $query after substituting ^, # and $ symbols, and return the result resource (or call fail handler). * Run $query after substituting ^, # and $ symbols, and return the result resource (or call fail handler).
* @deprecated 1.9.0 Use DbConnection->query() instead.
* @param string $query * @param string $query
* @return mixed * @return mixed
*/ */
...@@ -417,6 +261,7 @@ function qa_db_query_sub($query) // arguments for substitution retrieved using f ...@@ -417,6 +261,7 @@ function qa_db_query_sub($query) // arguments for substitution retrieved using f
/** /**
* Run $query after substituting ^, # and $ symbols, and return the result resource (or call fail handler). * Run $query after substituting ^, # and $ symbols, and return the result resource (or call fail handler).
* Query parameters are passed as an array. * Query parameters are passed as an array.
* @deprecated 1.9.0 Use DbConnection->query() instead.
* @param string $query * @param string $query
* @param array $params * @param array $params
* @return mixed * @return mixed
...@@ -429,15 +274,17 @@ function qa_db_query_sub_params($query, $params) ...@@ -429,15 +274,17 @@ function qa_db_query_sub_params($query, $params)
/** /**
* Return the number of rows in $result. (Simple wrapper for mysqli_result::num_rows.) * Return the number of rows in $result. (Simple wrapper for mysqli_result::num_rows.)
* @deprecated 1.9.0 Use DbResult->affectedRows() instead.
* @param $result * @param $result
* @return int * @return int
*/ */
function qa_db_num_rows($result) function qa_db_num_rows($result)
{ {
if ($result instanceof \Q2A\Database\DbResult) if ($result instanceof \Q2A\Database\DbResult)
return $result->rowCount(); return $result->affectedRows();
// backwards compatibility
if ($result instanceof mysqli_result) if ($result instanceof mysqli_result)
return $result->num_rows; return $result->num_rows;
...@@ -447,32 +294,28 @@ function qa_db_num_rows($result) ...@@ -447,32 +294,28 @@ function qa_db_num_rows($result)
/** /**
* Return the value of the auto-increment column for the last inserted row. * Return the value of the auto-increment column for the last inserted row.
* @deprecated 1.9.0 Use DbConnection->lastInsertId() instead.
*/ */
function qa_db_last_insert_id() function qa_db_last_insert_id()
{ {
return qa_service('database')->lastInsertId(); return qa_service('database')->lastInsertId();
$db = qa_db_connection();
return $db->insert_id;
} }
/** /**
* Return the number of rows affected by the last query. * Return the number of rows affected by the last query.
* @deprecated 1.9.0 Use DbResult->affectedRows() instead.
*/ */
function qa_db_affected_rows() function qa_db_affected_rows()
{ {
return \PDOstatement::rowCount(); // not doable with new DB system (requires a PDOStatement, which if we had we could pass into DbResult instead)
return 0;
$db = qa_db_connection();
return $db->affected_rows;
} }
/** /**
* For the previous INSERT ... ON DUPLICATE KEY UPDATE query, return whether an insert operation took place. * For the previous INSERT ... ON DUPLICATE KEY UPDATE query, return whether an insert operation took place.
* @deprecated 1.9.0 Use DbResult->affectedRows() instead.
*/ */
function qa_db_insert_on_duplicate_inserted() function qa_db_insert_on_duplicate_inserted()
{ {
...@@ -571,176 +414,37 @@ function qa_db_list_tables($onlyTablesWithPrefix = false) ...@@ -571,176 +414,37 @@ function qa_db_list_tables($onlyTablesWithPrefix = false)
/** /**
* Return the data specified by a single $selectspec - see long comment above. * Return the data specified by a single $selectspec - see long comment above.
* @deprecated 1.9.0 Use DbConnection->singleSelect() instead.
* @param $selectspec * @param $selectspec
* @return array|mixed * @return array|mixed
*/ */
function qa_db_single_select($selectspec) function qa_db_single_select($selectspec)
{ {
return qa_service('database')->singleSelect($selectspec); return qa_service('database')->singleSelect($selectspec);
// check for cached results
if (isset($selectspec['caching'])) {
$cacheDriver = \Q2A\Storage\CacheFactory::getCacheDriver();
$cacheKey = 'query:' . $selectspec['caching']['key'];
if ($cacheDriver->isEnabled()) {
$queryData = $cacheDriver->get($cacheKey);
if ($queryData !== null)
return $queryData;
}
}
$query = 'SELECT ';
foreach ($selectspec['columns'] as $columnas => $columnfrom) {
$query .= is_int($columnas) ? "$columnfrom, " : "$columnfrom AS `$columnas`, ";
}
$results = qa_db_read_all_assoc(qa_db_query_raw(qa_db_apply_sub(
substr($query, 0, -2) . (strlen(@$selectspec['source']) ? (' FROM ' . $selectspec['source']) : ''),
@$selectspec['arguments'])
), @$selectspec['arraykey']); // arrayvalue is applied in qa_db_post_select()
qa_db_post_select($results, $selectspec); // post-processing
// save cached results
if (isset($selectspec['caching'])) {
if ($cacheDriver->isEnabled()) {
$cacheDriver->set($cacheKey, $results, $selectspec['caching']['ttl']);
}
}
return $results;
} }
/** /**
* Return the data specified by each element of $selectspecs, where the keys of the * Return the data specified by each element of $selectspecs, where the keys of the
* returned array match the keys of the supplied $selectspecs array. See long comment above. * returned array match the keys of the supplied $selectspecs array. See long comment above.
* @deprecated 1.9.0 Use DbConnection->multiSelect() instead.
* @param array $selectspecs * @param array $selectspecs
* @return array * @return array
*/ */
function qa_db_multi_select($selectspecs) function qa_db_multi_select($selectspecs)
{ {
return qa_service('database')->multiSelect($selectspecs); return qa_service('database')->multiSelect($selectspecs);
if (!count($selectspecs))
return array();
// Perform simple queries if the database is local or there are only 0 or 1 selectspecs
if (!QA_OPTIMIZE_DISTANT_DB || (count($selectspecs) <= 1)) {
$outresults = array();
foreach ($selectspecs as $selectkey => $selectspec)
$outresults[$selectkey] = qa_db_single_select($selectspec);
return $outresults;
}
// Otherwise, parse columns for each spec to deal with columns without an 'AS' specification
foreach ($selectspecs as $selectkey => $selectspec) {
$selectspecs[$selectkey]['outcolumns'] = array();
$selectspecs[$selectkey]['autocolumn'] = array();
foreach ($selectspec['columns'] as $columnas => $columnfrom) {
if (is_int($columnas)) {
$periodpos = strpos($columnfrom, '.');
$columnas = is_numeric($periodpos) ? substr($columnfrom, $periodpos + 1) : $columnfrom;
$selectspecs[$selectkey]['autocolumn'][$columnas] = true;
}
if (isset($selectspecs[$selectkey]['outcolumns'][$columnas]))
qa_fatal_error('Duplicate column name in qa_db_multi_select()');
$selectspecs[$selectkey]['outcolumns'][$columnas] = $columnfrom;
}
if (isset($selectspec['arraykey']))
if (!isset($selectspecs[$selectkey]['outcolumns'][$selectspec['arraykey']]))
qa_fatal_error('Used arraykey not in columns in qa_db_multi_select()');
if (isset($selectspec['arrayvalue']))
if (!isset($selectspecs[$selectkey]['outcolumns'][$selectspec['arrayvalue']]))
qa_fatal_error('Used arrayvalue not in columns in qa_db_multi_select()');
}
// Work out the full list of columns used
$outcolumns = array();
foreach ($selectspecs as $selectspec)
$outcolumns = array_unique(array_merge($outcolumns, array_keys($selectspec['outcolumns'])));
// Build the query based on this full list
$query = '';
foreach ($selectspecs as $selectkey => $selectspec) {
$subquery = "(SELECT '" . qa_db_escape_string($selectkey) . "'" . (empty($query) ? ' AS selectkey' : '');
foreach ($outcolumns as $columnas) {
$subquery .= ', ' . (isset($selectspec['outcolumns'][$columnas]) ? $selectspec['outcolumns'][$columnas] : 'NULL');
if (empty($query) && !isset($selectspec['autocolumn'][$columnas]))
$subquery .= ' AS ' . $columnas;
}
if (strlen(@$selectspec['source']))
$subquery .= ' FROM ' . $selectspec['source'];
$subquery .= ')';
if (strlen($query))
$query .= ' UNION ALL ';
$query .= qa_db_apply_sub($subquery, @$selectspec['arguments']);
}
// Perform query and extract results
$rawresults = qa_db_read_all_assoc(qa_db_query_raw($query));
$outresults = array();
foreach ($selectspecs as $selectkey => $selectspec)
$outresults[$selectkey] = array();
foreach ($rawresults as $rawresult) {
$selectkey = $rawresult['selectkey'];
$selectspec = $selectspecs[$selectkey];
$keepresult = array();
foreach ($selectspec['outcolumns'] as $columnas => $columnfrom)
$keepresult[$columnas] = $rawresult[$columnas];
if (isset($selectspec['arraykey']))
$outresults[$selectkey][$keepresult[$selectspec['arraykey']]] = $keepresult;
else
$outresults[$selectkey][] = $keepresult;
}
// Post-processing to apply various stuff include sorting request, since we can't rely on ORDER BY due to UNION
foreach ($selectspecs as $selectkey => $selectspec)
qa_db_post_select($outresults[$selectkey], $selectspec);
// Return results
return $outresults;
} }
/** /**
* Post-process $outresult according to $selectspec, applying 'sortasc', 'sortdesc', 'arrayvalue' and 'single'. * Post-process $outresult according to $selectspec, applying 'sortasc', 'sortdesc', 'arrayvalue' and 'single'.
* @deprecated 1.9.0 Private method in DbConnection (code left in place for backwards compatibility)
* @param array $outresult * @param array $outresult
* @param array $selectspec * @param array $selectspec
*/ */
function qa_db_post_select(&$outresult, $selectspec) function qa_db_post_select(&$outresult, $selectspec)
{ {
return; // private method in DbConnection
// PHP's sorting algorithm is not 'stable', so we use '_order_' element to keep stability. // PHP's sorting algorithm is not 'stable', so we use '_order_' element to keep stability.
// By contrast, MySQL's ORDER BY does seem to give the results in a reliable order. // By contrast, MySQL's ORDER BY does seem to give the results in a reliable order.
...@@ -783,6 +487,7 @@ function qa_db_post_select(&$outresult, $selectspec) ...@@ -783,6 +487,7 @@ function qa_db_post_select(&$outresult, $selectspec)
* Return the full results from the $result resource as an array. The key of each element in the returned array * Return the full results from the $result resource as an array. The key of each element in the returned array
* is from column $key if specified, otherwise it's integer. The value of each element in the returned array * is from column $key if specified, otherwise it's integer. The value of each element in the returned array
* is from column $value if specified, otherwise it's a named array of all columns, given an array of arrays. * is from column $value if specified, otherwise it's a named array of all columns, given an array of arrays.
* @deprecated 1.9.0 Use DbResult->fetchAllAssoc() instead.
* @param $result * @param $result
* @param string $key * @param string $key
* @param mixed $value * @param mixed $value
...@@ -795,6 +500,7 @@ function qa_db_read_all_assoc($result, $key = null, $value = null) ...@@ -795,6 +500,7 @@ function qa_db_read_all_assoc($result, $key = null, $value = null)
} }
// backwards compatibility
if (!($result instanceof mysqli_result)) if (!($result instanceof mysqli_result))
qa_fatal_error('Reading all assoc from invalid result'); qa_fatal_error('Reading all assoc from invalid result');
...@@ -814,6 +520,7 @@ function qa_db_read_all_assoc($result, $key = null, $value = null) ...@@ -814,6 +520,7 @@ function qa_db_read_all_assoc($result, $key = null, $value = null)
/** /**
* Return the first row from the $result resource as an array of [column name] => [column value]. * Return the first row from the $result resource as an array of [column name] => [column value].
* If there's no first row, throw a fatal error unless $allowempty is true. * If there's no first row, throw a fatal error unless $allowempty is true.
* @deprecated 1.9.0 Use DbResult->fetchNextAssoc() instead.
* @param $result * @param $result
* @param bool $allowempty * @param bool $allowempty
* @return array|null * @return array|null
...@@ -825,6 +532,7 @@ function qa_db_read_one_assoc($result, $allowempty = false) ...@@ -825,6 +532,7 @@ function qa_db_read_one_assoc($result, $allowempty = false)
} }
// backwards compatibility
if (!($result instanceof mysqli_result)) if (!($result instanceof mysqli_result))
qa_fatal_error('Reading one assoc from invalid result'); qa_fatal_error('Reading one assoc from invalid result');
...@@ -842,6 +550,7 @@ function qa_db_read_one_assoc($result, $allowempty = false) ...@@ -842,6 +550,7 @@ function qa_db_read_one_assoc($result, $allowempty = false)
/** /**
* Return a numbered array containing the first (and presumably only) column from the $result resource. * Return a numbered array containing the first (and presumably only) column from the $result resource.
* @deprecated 1.9.0 Use DbResult->fetchAllValues() instead.
* @param $result * @param $result
* @return array * @return array
*/ */
...@@ -852,6 +561,7 @@ function qa_db_read_all_values($result) ...@@ -852,6 +561,7 @@ function qa_db_read_all_values($result)
} }
// backwards compatibility
if (!($result instanceof mysqli_result)) if (!($result instanceof mysqli_result))
qa_fatal_error('Reading column from invalid result'); qa_fatal_error('Reading column from invalid result');
...@@ -867,6 +577,7 @@ function qa_db_read_all_values($result) ...@@ -867,6 +577,7 @@ function qa_db_read_all_values($result)
/** /**
* Return the first column of the first row (and presumably only cell) from the $result resource. * Return the first column of the first row (and presumably only cell) from the $result resource.
* If there's no first row, throw a fatal error unless $allowempty is true. * If there's no first row, throw a fatal error unless $allowempty is true.
* @deprecated 1.9.0 Use DbResult->fetchOneValue() instead.
* @param $result * @param $result
* @param bool $allowempty * @param bool $allowempty
* @return mixed|null * @return mixed|null
...@@ -878,6 +589,7 @@ function qa_db_read_one_value($result, $allowempty = false) ...@@ -878,6 +589,7 @@ function qa_db_read_one_value($result, $allowempty = false)
} }
// backwards compatibility
if (!($result instanceof mysqli_result)) if (!($result instanceof mysqli_result))
qa_fatal_error('Reading one value from invalid result'); qa_fatal_error('Reading one value from invalid result');
...@@ -896,30 +608,21 @@ function qa_db_read_one_value($result, $allowempty = false) ...@@ -896,30 +608,21 @@ function qa_db_read_one_value($result, $allowempty = false)
/** /**
* Suspend the updating of counts (of many different types) in the database, to save time when making a lot of changes * Suspend the updating of counts (of many different types) in the database, to save time when making a lot of changes
* if $suspend is true, otherwise reinstate it. A counter is kept to allow multiple calls. * if $suspend is true, otherwise reinstate it. A counter is kept to allow multiple calls.
* @deprecated 1.9.0 Use DbConnection->suspendUpdateCounts() instead.
* @param bool $suspend * @param bool $suspend
*/ */
function qa_suspend_update_counts($suspend = true) function qa_suspend_update_counts($suspend = true)
{ {
qa_service('database')->suspendUpdateCounts($suspend); qa_service('database')->suspendUpdateCounts($suspend);
return;
global $qa_update_counts_suspended;
$qa_update_counts_suspended += ($suspend ? 1 : -1);
} }
/** /**
* Returns whether counts should currently be updated (i.e. if count updating has not been suspended). * Returns whether counts should currently be updated (i.e. if count updating has not been suspended).
* @deprecated 1.9.0 Use DbConnection->shouldUpdateCounts() instead.
* @return bool * @return bool
*/ */
function qa_should_update_counts() function qa_should_update_counts()
{ {
return qa_service('database')->shouldUpdateCounts(); return qa_service('database')->shouldUpdateCounts();
global $qa_update_counts_suspended;
return ($qa_update_counts_suspended <= 0);
} }
...@@ -302,7 +302,7 @@ class DbConnection ...@@ -302,7 +302,7 @@ class DbConnection
$arraykey = isset($selectspec['arraykey']) ? $selectspec['arraykey'] : null; $arraykey = isset($selectspec['arraykey']) ? $selectspec['arraykey'] : null;
$result = $this->query($query, $params); $result = $this->query($query, $params);
$data = $result->fetchAllAssoc($arraykey); // arrayvalue is applied in qa_db_post_select() $data = $result->fetchAllAssoc($arraykey); // arrayvalue is applied in formatSelect()
$this->formatSelect($data, $selectspec); // post-processing $this->formatSelect($data, $selectspec); // post-processing
......
...@@ -128,7 +128,7 @@ class DbResult ...@@ -128,7 +128,7 @@ class DbResult
* Number of rows found (SELECT queries) or rows affected (UPDATE/INSERT/DELETE queries). * Number of rows found (SELECT queries) or rows affected (UPDATE/INSERT/DELETE queries).
* @return int * @return int
*/ */
public function rowCount() public function affectedRows()
{ {
return $this->stmt->rowCount(); return $this->stmt->rowCount();
} }
...@@ -140,7 +140,7 @@ class DbResult ...@@ -140,7 +140,7 @@ class DbResult
*/ */
public function isEmpty() public function isEmpty()
{ {
return $this->stmt->rowCount() === 0; return $this->affectedRows() === 0;
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment