20 const DELAYED_QUERY =
'q';
21 const DELAYED_TYPE =
't';
22 const DELAYED_HANDLER =
'h';
23 const DELAYED_PARAMS =
'p';
28 private $table_prefix;
33 private $connections = [];
38 private $query_count = 0;
51 private $query_cache = null;
56 private $query_cache_size = 50;
65 private $delayed_queries = array();
70 private $installed =
false;
90 $this->logger = $logger;
91 $this->config = $config;
93 $this->table_prefix = $config->getTablePrefix();
95 $this->enableQueryCache();
106 $this->logger = $logger;
118 if (isset($this->connections[
$type])) {
119 return $this->connections[
$type];
120 }
else if (isset($this->connections[
'readwrite'])) {
121 return $this->connections[
'readwrite'];
123 $this->setupConnections();
124 return $this->getConnection($type);
139 if ($this->config->isDatabaseSplit()) {
140 $this->connect(
'read');
141 $this->connect(
'write');
143 $this->connect(
'readwrite');
159 $conf = $this->config->getConnectionConfig(
$type);
162 'dbname' => $conf[
'database'],
163 'user' => $conf[
'user'],
164 'password' => $conf[
'password'],
165 'host' => $conf[
'host'],
167 'driver' =>
'pdo_mysql',
171 $this->connections[
$type] = DriverManager::getConnection(
$params);
172 $this->connections[
$type]->setFetchMode(\PDO::FETCH_OBJ);
175 $sub_query =
"SELECT REPLACE(@@SESSION.sql_mode, 'ONLY_FULL_GROUP_BY', '')";
176 $this->connections[
$type]->exec(
"SET SESSION sql_mode=($sub_query);");
178 }
catch (\PDOException
$e) {
181 if ($e->getCode() == 1102 || $e->getCode() == 1049) {
182 $msg =
"Elgg couldn't select the database '{$conf['database']}'. " 183 .
"Please check that the database is created and you have access to it.";
185 $msg =
"Elgg couldn't connect to the database using the given credentials. Check the settings file.";
187 throw new \DatabaseException($msg);
209 return $this->getResults($query, $callback,
false,
$params);
227 return $this->getResults($query, $callback,
true,
$params);
245 $this->logger->info(
"DB query $query");
248 $connection = $this->getConnection(
'write');
250 $this->invalidateQueryCache();
252 $this->executeQuery($query, $connection,
$params);
253 return (
int)$connection->lastInsertId();
273 $this->logger->info(
"DB query $query");
276 $this->invalidateQueryCache();
278 $stmt = $this->executeQuery($query, $this->getConnection(
'write'),
$params);
280 return $stmt->rowCount();
300 $this->logger->info(
"DB query $query");
303 $connection = $this->getConnection(
'write');
305 $this->invalidateQueryCache();
307 $stmt = $this->executeQuery(
"$query", $connection,
$params);
308 return (
int)$stmt->rowCount();
325 if (is_string($callback)) {
328 if (is_object($callback)) {
329 return spl_object_hash($callback) .
"::__invoke";
331 if (is_array($callback)) {
332 if (is_string($callback[0])) {
333 return "{$callback[0]}::{$callback[1]}";
335 return spl_object_hash($callback[0]) .
"::{$callback[1]}";
359 $query_id = (int)$single . $query .
'|';
361 $query_id .= serialize(
$params) .
'|';
365 if (!is_callable($callback)) {
366 $inspector = new \Elgg\Debug\Inspector();
367 throw new \RuntimeException(
'$callback must be a callable function. Given ' . $inspector->describeCallable($callback));
369 $query_id .= $this->fingerprintCallback($callback);
372 $hash = md5($query_id);
375 if ($this->query_cache) {
376 if (isset($this->query_cache[$hash])) {
379 $this->logger->info(
"DB query $query results returned from cache (hash: $hash)");
381 return $this->query_cache[$hash];
387 $stmt = $this->executeQuery($query, $this->getConnection(
'read'),
$params);
388 while (
$row = $stmt->fetch()) {
390 $row = call_user_func($callback,
$row);
402 if ($this->query_cache) {
403 $this->query_cache[$hash] =
$return;
406 $this->logger->info(
"DB query $query results cached (hash: $hash)");
427 if ($query == null) {
428 throw new \DatabaseException(
"Query cannot be null");
431 $this->query_count++;
434 $timer_key = preg_replace(
'~\\s+~',
' ', trim($query .
'|' . serialize(
$params)));
435 $this->timer->begin([
'SQL', $timer_key]);
443 $value = $connection->query($query);
446 throw new \DatabaseException($e->getMessage() .
"\n\n" 447 .
"QUERY: $query \n\n" 448 .
"PARAMS: " . print_r(
$params,
true),
454 $this->timer->end([
'SQL', $timer_key]);
486 $script = file_get_contents($scriptlocation);
492 $script = preg_replace(
'/^(?:--|#) .*$/m',
'', $script);
495 $sql_statements = preg_split(
'/;[\n\r]+/',
"$script\n");
497 foreach ($sql_statements as $statement) {
498 $statement = trim($statement);
499 $statement = str_replace(
"prefix_", $this->table_prefix, $statement);
500 if (!empty($statement)) {
502 $this->updateData($statement);
504 $errors[] = $e->getMessage();
508 if (!empty($errors)) {
510 foreach ($errors as
$error) {
511 $errortxt .=
" {$error};";
514 $msg =
"There were a number of issues: " . $errortxt;
515 throw new \DatabaseException($msg);
518 $msg =
"Elgg couldn't find the requested database script at " . $scriptlocation .
".";
519 throw new \DatabaseException($msg);
542 $this->delayed_queries[] = [
543 self::DELAYED_QUERY => $query,
544 self::DELAYED_TYPE =>
$type,
545 self::DELAYED_HANDLER => $callback,
546 self::DELAYED_PARAMS =>
$params,
562 foreach ($this->delayed_queries as $set) {
563 $query = $set[self::DELAYED_QUERY];
564 $type = $set[self::DELAYED_TYPE];
565 $handler = $set[self::DELAYED_HANDLER];
566 $params = $set[self::DELAYED_PARAMS];
570 $stmt = $this->executeQuery($query, $this->getConnection(
$type),
$params);
578 $this->logger->error($e);
593 if ($this->config->isQueryCacheEnabled() && $this->query_cache === null) {
595 $this->query_cache = new \Elgg\Cache\LRUCache($this->query_cache_size);
609 $this->query_cache = null;
618 if ($this->query_cache) {
619 $this->query_cache->clear();
621 $this->logger->info(
"Query cache invalidated");
640 $sql =
"SELECT value FROM {$this->table_prefix}datalists WHERE name = 'installed'";
641 $this->getConnection(
'read')->query($sql);
643 throw new \InstallationException(
"Unable to handle this request. This site is not configured or the database is down.");
656 return $this->query_count;
668 if (function_exists(
'elgg_deprecated_notice')) {
671 return $this->table_prefix;
685 if ($signed ===
false) {
704 throw new \DatabaseException(__METHOD__ .
'() and serialize_string() cannot accept arrays.');
706 $quoted = $this->getConnection(
'read')->quote(
$value);
707 if ($quoted[0] !==
"'" || substr($quoted, -1) !==
"'") {
708 throw new \DatabaseException(
"PDO::quote did not return surrounding single quotes.");
710 return substr($quoted, 1, -1);
722 $driver = $this->getConnection(
$type)->getWrappedConnection();
723 if ($driver instanceof ServerInfoAwareConnection) {
724 return $driver->getServerVersion();
737 if (
$name ===
'prefix') {
738 return $this->table_prefix;
741 throw new \RuntimeException(
"Cannot read property '$name'");
752 throw new \RuntimeException(
"Cannot write property '$name'");
updateData($query, $get_num_rows=false, array $params=[])
Update the database.
if(!$owner||!($owner instanceof ElggUser)||!$owner->canEdit()) $error
setLogger(Logger $logger)
Set the logger object.
getQueryCount()
Get the number of queries made to the database.
__construct(\Elgg\Database\Config $config,\Elgg\Logger $logger=null)
Constructor.
if($guid==elgg_get_logged_in_user_guid()) $name
invalidateQueryCache()
Invalidate the query cache.
$CONFIG installed
Is the site fully installed.
Access to configuration values.
executeQuery($query, Connection $connection, array $params=[])
Execute a query.
trait Profilable
Make an object accept a timer.
sanitizeInt($value, $signed=true)
Sanitizes an integer value for use in a query.
getData($query, $callback=null, array $params=[])
Retrieve rows from the database.
__set($name, $value)
Handle magic property writes.
sanitizeString($value)
Sanitizes a string for use in a query.
__get($name)
Handle magic property reads.
assertInstalled()
Test that the Elgg database is installed.
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
runSqlScript($scriptlocation)
Runs a full database script from disk.
registerDelayedQuery($query, $type, $callback=null, array $params=[])
Queue a query for execution upon shutdown.
fingerprintCallback($callback)
Get a string that uniquely identifies a callback during the current request.
getResults($query, $callback=null, $single=false, array $params=[])
Handles queries that return results, running the results through a an optional callback function...
connect($type="readwrite")
Establish a connection to the database server.
deleteData($query, array $params=[])
Delete data from the database.
getConnection($type)
Gets (if required, also creates) a DB connection.
disableQueryCache()
Disable the query cache.
enableQueryCache()
Enable the query cache.
getDataRow($query, $callback=null, array $params=[])
Retrieve a single row from the database.
getServerVersion($type)
Get the server version number.
executeDelayedQueries()
Trigger all queries that were registered as "delayed" queries.
setupConnections()
Establish database connections.
insertData($query, array $params=[])
Insert a row into the database.
http free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
getTablePrefix()
Get the value of the "prefix" property.