29 const DELAYED_QUERY =
'q';
30 const DELAYED_TYPE =
't';
31 const DELAYED_HANDLER =
'h';
32 const DELAYED_PARAMS =
'p';
37 private $table_prefix;
42 private $connections = [];
47 private $query_count = 0;
63 protected $delayed_queries = [];
77 $this->query_cache = $query_cache;
79 $this->resetConnections($config);
90 $this->closeConnections();
94 $this->query_cache->enable();
95 $this->query_cache->clear();
107 foreach ($this->connections as $connection) {
108 $connection->close();
111 $this->connections = [];
122 if (isset($this->connections[$type])) {
123 return $this->connections[
$type];
124 }
else if (isset($this->connections[
'readwrite'])) {
125 return $this->connections[
'readwrite'];
128 $this->setupConnections();
130 return $this->getConnection($type);
142 if ($this->config->isDatabaseSplit()) {
143 $this->connect(
'read');
144 $this->connect(
'write');
146 $this->connect(
'readwrite');
161 $conf = $this->config->getConnectionConfig(
$type);
164 'dbname' => $conf[
'database'],
165 'user' => $conf[
'user'],
166 'password' => $conf[
'password'],
167 'host' => $conf[
'host'],
168 'port' => $conf[
'port'],
169 'charset' => $conf[
'encoding'],
170 'driver' =>
'pdo_mysql',
174 $this->connections[
$type] = DriverManager::getConnection(
$params);
177 $sub_query =
"SELECT REPLACE(@@SESSION.sql_mode, 'ONLY_FULL_GROUP_BY', '')";
178 $this->connections[
$type]->executeStatement(
"SET SESSION sql_mode=($sub_query);");
181 $this->
log(LogLevel::ERROR, $e);
183 if ($e->getCode() == 1102 || $e->getCode() == 1049) {
184 $msg =
"Elgg couldn't select the database '{$conf['database']}'. " 185 .
"Please check that the database is created and you have access to it.";
187 $msg =
"Elgg couldn't connect to the database using the given credentials. Check the settings file.";
210 if (!
$query instanceof QueryBuilder) {
211 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
231 if (!
$query instanceof QueryBuilder) {
232 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
249 if (!
$query instanceof QueryBuilder) {
250 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
254 $connection = $this->getConnection(
'write');
255 if (
$query instanceof QueryBuilder) {
258 $connection =
$query->getConnection();
261 $this->
getLogger()->info(
"DB insert query {$sql} (params: " . print_r(
$params,
true) .
")");
263 $this->query_cache->clear();
266 return (
int) $connection->lastInsertId();
281 if (!
$query instanceof QueryBuilder) {
282 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
286 if (
$query instanceof QueryBuilder) {
291 $this->
getLogger()->info(
"DB update query {$sql} (params: " . print_r(
$params,
true) .
")");
293 $this->query_cache->clear();
296 if (!$get_num_rows) {
314 if (!
$query instanceof QueryBuilder) {
315 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
319 if (
$query instanceof QueryBuilder) {
324 $this->
getLogger()->info(
"DB delete query {$sql} (params: " . print_r(
$params,
true) .
")");
326 $this->query_cache->clear();
344 if (is_string($callback)) {
348 if (is_object($callback)) {
349 return spl_object_hash($callback) .
'::__invoke';
352 if (is_array($callback)) {
353 if (is_string($callback[0])) {
354 return "{$callback[0]}::{$callback[1]}";
357 return spl_object_hash($callback[0]) .
"::{$callback[1]}";
379 if (
$query instanceof QueryBuilder) {
389 $extras = (int) $single .
'|';
391 if (!is_callable($callback)) {
392 throw new \RuntimeException(
'$callback must be a callable function. Given ' 395 $extras .= $this->fingerprintCallback($callback);
398 $hash = $this->query_cache->getHash($sql,
$params, $extras);
400 $cached_results = $this->query_cache->get($hash);
401 if (isset($cached_results)) {
402 return $cached_results;
405 $this->
getLogger()->info(
"DB select query {$sql} (params: " . print_r(
$params,
true) .
")");
409 if (
$query instanceof QueryBuilder) {
410 $stmt = $this->executeQuery(
$query,
$query->getConnection());
412 $stmt = $this->executeQuery(
$query, $this->getConnection(
'read'),
$params);
415 while ($row = $stmt->fetchAssociative()) {
416 $row_obj = (object) $row;
418 $row_obj = call_user_func($callback, $row_obj);
425 $return[] = $row_obj;
430 $this->query_cache->set($hash, $return);
454 if (
$query instanceof QueryBuilder) {
460 if (
substr($param_key, 0, 1) !==
':') {
464 $this->
getLogger()->warning(
'Unsupported colon detected in named param: ' . $param_key);
472 if (
$query instanceof QueryBuilder) {
473 if (
$query->getType() === QueryBuilder::SELECT) {
474 return $query->executeQuery();
476 return $query->executeStatement();
479 return $connection->executeQuery($sql,
$params);
482 return $connection->executeQuery($sql);
508 if (
$query instanceof QueryBuilder) {
509 $params =
$query->getParameters();
513 $this->query_count++;
515 $timer_key = preg_replace(
'~\\s+~',
' ',
trim($sql .
'|' . serialize($params)));
518 $stop_timer =
function() use ($timer_key) {
519 $this->
endTimer([
'SQL', $timer_key]);
549 if (!
$query instanceof QueryBuilder) {
550 $this->
logDeprecatedMessage(
'The use of non ' . QueryBuilder::class .
' queries in ' . __METHOD__ .
' has been deprecated',
'4.0');
553 if ($type !==
'read' && $type !==
'write') {
557 $this->delayed_queries[] = [
558 self::DELAYED_QUERY =>
$query,
559 self::DELAYED_TYPE =>
$type,
560 self::DELAYED_HANDLER => $callback,
561 self::DELAYED_PARAMS =>
$params,
575 foreach ($this->delayed_queries as $set) {
576 $query = $set[self::DELAYED_QUERY];
577 $type = $set[self::DELAYED_TYPE];
578 $handler = $set[self::DELAYED_HANDLER];
579 $params = $set[self::DELAYED_PARAMS];
593 $this->delayed_queries = [];
604 $this->query_cache->enable();
616 $this->query_cache->disable();
625 return $this->query_count;
636 $driver = $this->getConnection(
$type)->getWrappedConnection();
637 if ($driver instanceof ServerInfoAwareConnection) {
638 $version = $driver->getServerVersion();
640 if ($this->isMariaDB(
$type)) {
660 $driver = $this->getConnection(
$type)->getWrappedConnection();
661 if ($driver instanceof ServerInfoAwareConnection) {
662 $version = $driver->getServerVersion();
664 return stristr(
$version,
'mariadb') !==
false;
679 if (
$name ===
'prefix') {
680 return $this->table_prefix;
683 throw new \RuntimeException(
"Cannot read property '$name'");
696 throw new \RuntimeException(
"Cannot write property '$name'");
trait Profilable
Make an object accept a timer.
if(!$user||!$user->canDelete()) $name
getQueryCount()
Get the number of queries made to the database.
$params
Saves global plugin settings.
Database configuration service.
getConnection(string $type)
Gets (if required, also creates) a DB connection.
__construct(DbConfig $config, QueryCache $query_cache)
Constructor.
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
executeQuery($query, Connection $connection, array $params=[])
Execute a query.
resetConnections(DbConfig $config)
Reset the connections with new credentials.
$config
Advanced site settings, debugging section.
setParameters(array $params)
Set query parameters.
trait Loggable
Enables adding a logger.
getData($query, $callback=null, array $params=[])
Retrieve rows from the database.
__set($name, $value)
Handle magic property writes.
__get($name)
Handle magic property reads.
getTablePrefix()
Get the database table prefix.
isMariaDB(string $type=DbConfig::READ_WRITE)
Is the database MariaDB.
Volatile cache for select queries.
A generic parent class for database exceptions.
Result of a single BatchUpgrade run.
fingerprintCallback($callback)
Get a string that uniquely identifies a callback during the current request.
log($level, $message, array $context=[])
Log a message.
getLogger()
Returns logger.
deleteData($query, array $params=[])
Delete data from the database.
disableQueryCache()
Disable the query cache.
if($item instanceof\ElggEntity) elseif($item instanceof\ElggRiverItem) elseif($item instanceof ElggRelationship) elseif(is_callable([$item, 'getType']))
beginTimer(array $keys)
Start the timer (when enabled)
updateData($query, bool $get_num_rows=false, array $params=[])
Update the database.
enableQueryCache()
Enable the query cache.
getDataRow($query, $callback=null, array $params=[])
Retrieve a single row from the database.
_elgg_services()
Get the global service provider.
executeDelayedQueries()
Trigger all queries that were registered as "delayed" queries.
getServerVersion(string $type=DbConfig::READ_WRITE)
Get the server version number.
closeConnections()
Close all database connections.
setupConnections()
Establish database connections.
insertData($query, array $params=[])
Insert a row into the database.
connect(string $type= 'readwrite')
Establish a connection to the database server.
trackQuery($query, array $params, callable $callback)
Tracks the query count and timers for a given query.
getResults($query, $callback=null, bool $single=false, array $params=[])
Handles queries that return results, running the results through a an optional callback function...
endTimer(array $keys)
Ends the timer (when enabled)
registerDelayedQuery($query, string $type, $callback=null, array $params=[])
Queue a query for execution upon shutdown.
logDeprecatedMessage(string $message, string $version)
Sends a message about deprecated use of a function, view, etc.