Commit 3ac1100c by Scott

Move queued selectspecs to DbSelect

parent 5b736070
...@@ -37,7 +37,7 @@ require_once QA_INCLUDE_DIR.'db/maxima.php'; ...@@ -37,7 +37,7 @@ require_once QA_INCLUDE_DIR.'db/maxima.php';
function qa_db_select_with_pending() // any number of parameters read via func_get_args() function qa_db_select_with_pending() // any number of parameters read via func_get_args()
{ {
$selectspecs = func_get_args(); $selectspecs = func_get_args();
$dbSelect = new \Q2A\Database\DbSelect(qa_service('database')); $dbSelect = qa_service('dbselect');
return qa_call([$dbSelect, 'selectWithPending'], $selectspecs); return qa_call([$dbSelect, 'selectWithPending'], $selectspecs);
} }
...@@ -45,67 +45,52 @@ function qa_db_select_with_pending() // any number of parameters read via func_g ...@@ -45,67 +45,52 @@ function qa_db_select_with_pending() // any number of parameters read via func_g
/** /**
* Queue a $selectspec for running later, with $pendingid (used for retrieval) * Queue a $selectspec for running later, with $pendingid (used for retrieval)
* @deprecated 1.9.0 Use DbSelect->queuePending() instead.
* @param string $pendingid * @param string $pendingid
* @param array $selectspec * @param array $selectspec
*/ */
function qa_db_queue_pending_select($pendingid, $selectspec) function qa_db_queue_pending_select($pendingid, $selectspec)
{ {
global $qa_db_pending_selectspecs; qa_service('dbselect')->queuePending($pendingid, $selectspec);
$qa_db_pending_selectspecs[$pendingid] = $selectspec;
} }
/** /**
* Get the result of the queued SELECT query identified by $pendingid. Run the query if it hasn't run already. If * Get the result of the queued SELECT query identified by $pendingid. Run the query if it hasn't run already. If
* $selectspec is supplied, it doesn't matter if this hasn't been queued before - it will be queued and run now. * $selectspec is supplied, it doesn't matter if this hasn't been queued before - it will be queued and run now.
* @deprecated 1.9.0 Use DbSelect->getPendingResult() instead.
* @param string $pendingid * @param string $pendingid
* @param array|null $selectspec * @param array|null $selectspec
* @return mixed * @return mixed
*/ */
function qa_db_get_pending_result($pendingid, $selectspec = null) function qa_db_get_pending_result($pendingid, $selectspec = null)
{ {
global $qa_db_pending_selectspecs, $qa_db_pending_results; return qa_service('dbselect')->getPendingResult($pendingid, $selectspec);
if (isset($selectspec)) {
qa_db_queue_pending_select($pendingid, $selectspec);
} elseif (!isset($qa_db_pending_selectspecs[$pendingid])) {
qa_fatal_error('Pending query was never set up: ' . $pendingid);
}
if (!isset($qa_db_pending_results[$pendingid])) {
qa_db_select_with_pending();
}
return $qa_db_pending_results[$pendingid];
} }
/** /**
* Remove the results of queued SELECT query identified by $pendingid if it has already been run. This means it will * Remove the results of queued SELECT query identified by $pendingid if it has already been run. This means it will
* run again if its results are requested via qa_db_get_pending_result() * run again if its results are requested via qa_db_get_pending_result()
* @deprecated 1.9.0 Use DbSelect->flushPendingResult() instead.
* @param string $pendingid * @param string $pendingid
*/ */
function qa_db_flush_pending_result($pendingid) function qa_db_flush_pending_result($pendingid)
{ {
global $qa_db_pending_results; qa_service('dbselect')->flushPendingResult($pendingid);
unset($qa_db_pending_results[$pendingid]);
} }
/** /**
* Modify a selectspec to count the number of items. This assumes the original selectspec does not have a LIMIT clause. * Modify a selectspec to count the number of items. This assumes the original selectspec does not have a LIMIT clause.
* Currently works with message inbox/outbox functions and user-flags function. * Currently works with message inbox/outbox functions and user-flags function.
* @deprecated 1.9.0 Use DbSelect->selectspecWithCount() instead.
* @param array $selectspec * @param array $selectspec
* @return array * @return array
*/ */
function qa_db_selectspec_count($selectspec) function qa_db_selectspec_count($selectspec)
{ {
$selectspec['columns'] = array('count' => 'COUNT(*)'); return qa_service('dbselect')->selectspecWithCount($selectspec);
$selectspec['single'] = true;
unset($selectspec['arraykey']);
return $selectspec;
} }
......
...@@ -1899,7 +1899,7 @@ function qa_app() ...@@ -1899,7 +1899,7 @@ function qa_app()
/** /**
* Helper function to access services in the Container. * Helper function to get/set services.
* If the $key parameter is set and the $object parameter is null the container is called to resolve the $key. * If the $key parameter is set and the $object parameter is null the container is called to resolve the $key.
* If the $key and the $object parameters are null the container is called to bind the $object to the $key. * If the $key and the $object parameters are null the container is called to bind the $object to the $key.
* @param mixed $key Identifier for the object to get/set. * @param mixed $key Identifier for the object to get/set.
...@@ -1911,10 +1911,10 @@ function qa_service($key, $object = null) ...@@ -1911,10 +1911,10 @@ function qa_service($key, $object = null)
$app = Application::getInstance(); $app = Application::getInstance();
if ($object === null) { if ($object === null) {
return $app->getContainer()->get($key); return $app->getService($key);
} }
$app->getContainer()->set($key, $object); $app->registerService($key, $object);
} }
......
...@@ -435,7 +435,7 @@ function qa_db_list_tables($onlyTablesWithPrefix = false) ...@@ -435,7 +435,7 @@ function qa_db_list_tables($onlyTablesWithPrefix = false)
*/ */
function qa_db_single_select($selectspec) function qa_db_single_select($selectspec)
{ {
$dbSelect = new \Q2A\Database\DbSelect(qa_service('database')); $dbSelect = qa_service('dbselect');
return $dbSelect->singleSelect($selectspec); return $dbSelect->singleSelect($selectspec);
} }
...@@ -450,7 +450,7 @@ function qa_db_single_select($selectspec) ...@@ -450,7 +450,7 @@ function qa_db_single_select($selectspec)
*/ */
function qa_db_multi_select($selectspecs) function qa_db_multi_select($selectspecs)
{ {
$dbSelect = new \Q2A\Database\DbSelect(qa_service('database')); $dbSelect = qa_service('dbselect');
return $dbSelect->multiSelect($selectspecs); return $dbSelect->multiSelect($selectspecs);
} }
......
...@@ -18,20 +18,27 @@ ...@@ -18,20 +18,27 @@
namespace Q2A\App; namespace Q2A\App;
use Q2A\Http\Router;
use Q2A\Database\DbConnection; use Q2A\Database\DbConnection;
use Q2A\Database\DbSelect;
use Q2A\Exceptions\FatalErrorException;
use Q2A\Http\Router;
use Q2A\Util\Set;
class Application class Application
{ {
/** @var Container */ /** @var Set */
private $container; protected $services;
/** @var Set */
protected $dataStore;
/** @var static */ /** @var static */
protected static $instance; protected static $instance;
protected function __construct() protected function __construct()
{ {
$this->container = new Container(); $this->services = new Set();
$this->dataStore = new Set();
$this->registerCoreServices(); $this->registerCoreServices();
} }
...@@ -49,20 +56,56 @@ class Application ...@@ -49,20 +56,56 @@ class Application
} }
/** /**
* Register the services used by the core. * Return the specified service.
* @throws FatalErrorException
* @param string $key The key to look for
* @return mixed
*/ */
private function registerCoreServices() public function getService($key)
{
$obj = $this->services->get($key);
if ($obj === null) {
throw new FatalErrorException(sprintf('Key "%s" not found in container', $key));
}
return $obj;
}
/**
* Adds a new service to the container.
* @param string $key The key to look for
* @param mixed $value The object to add
* @return void
*/
public function registerService($key, $value)
{ {
$this->container->set('router', new Router()); $this->services->set($key, $value);
$this->container->set('database', new DbConnection());
} }
/** /**
* Return the container instance. * Retrieve data from the global storage.
* @return Container
*/ */
public function getContainer() public function getData($key)
{
return $this->dataStore->get($key);
}
/**
* Store some data in the global storage.
*/
public function setData($key, $value)
{
return $this->dataStore->set($key, $value);
}
/**
* Register the services used by the core.
*/
private function registerCoreServices()
{ {
return $this->container; $db = new DbConnection();
$this->services->set('router', new Router());
$this->services->set('database', $db);
$this->services->set('dbselect', new DbSelect($db));
} }
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
namespace Q2A\Database; namespace Q2A\Database;
use Q2A\Storage\CacheFactory; use Q2A\Storage\CacheFactory;
use Q2A\Util\Set;
/* /*
The selectspec array can contain the elements below. See db/selects.php for lots of examples. The selectspec array can contain the elements below. See db/selects.php for lots of examples.
...@@ -67,8 +68,15 @@ use Q2A\Storage\CacheFactory; ...@@ -67,8 +68,15 @@ use Q2A\Storage\CacheFactory;
class DbSelect class DbSelect
{ {
/** @var DbConnection */
protected $db; protected $db;
/** @var array */
protected $pendingSelects = [];
/** @var array */
protected $pendingResults = [];
public function __construct(DbConnection $db) public function __construct(DbConnection $db)
{ {
$this->db = $db; $this->db = $db;
...@@ -254,8 +262,6 @@ class DbSelect ...@@ -254,8 +262,6 @@ class DbSelect
{ {
require_once QA_INCLUDE_DIR . 'app/options.php'; require_once QA_INCLUDE_DIR . 'app/options.php';
global $qa_db_pending_selectspecs, $qa_db_pending_results;
$selectspecs = func_get_args(); $selectspecs = func_get_args();
$singleresult = (count($selectspecs) == 1); $singleresult = (count($selectspecs) == 1);
$outresults = array(); $outresults = array();
...@@ -267,22 +273,18 @@ class DbSelect ...@@ -267,22 +273,18 @@ class DbSelect
} }
} }
if (is_array($qa_db_pending_selectspecs)) { foreach ($this->pendingSelects as $pendingid => $selectspec) {
foreach ($qa_db_pending_selectspecs as $pendingid => $selectspec) { if (!isset($this->pendingResults[$pendingid])) {
if (!isset($qa_db_pending_results[$pendingid])) { $selectspecs['pending_' . $pendingid] = $selectspec;
$selectspecs['pending_' . $pendingid] = $selectspec;
}
} }
} }
$outresults = $outresults + $this->multiSelect($selectspecs); $outresults = $outresults + $this->multiSelect($selectspecs);
if (is_array($qa_db_pending_selectspecs)) { foreach ($this->pendingSelects as $pendingid => $selectspec) {
foreach ($qa_db_pending_selectspecs as $pendingid => $selectspec) { if (!isset($this->pendingResults[$pendingid])) {
if (!isset($qa_db_pending_results[$pendingid])) { $this->pendingResults[$pendingid] = $outresults['pending_' . $pendingid];
$qa_db_pending_results[$pendingid] = $outresults['pending_' . $pendingid]; unset($outresults['pending_' . $pendingid]);
unset($outresults['pending_' . $pendingid]);
}
} }
} }
...@@ -290,6 +292,64 @@ class DbSelect ...@@ -290,6 +292,64 @@ class DbSelect
} }
/** /**
* Queue a $selectspec for running later, with $pendingid (used for retrieval)
* @param string $pendingid
* @param array $selectspec
*/
public function queuePending($pendingid, $selectspec)
{
$this->pendingSelects[$pendingid] = $selectspec;
}
/**
* Get the result of the queued SELECT query identified by $pendingid. Run the query if it hasn't run already. If
* $selectspec is supplied, it doesn't matter if this hasn't been queued before - it will be queued and run now.
* @param string $pendingid
* @param array|null $selectspec
* @return mixed
*/
public function getPendingResult($pendingid, $selectspec = null)
{
if (isset($selectspec)) {
$this->queuePending($pendingid, $selectspec);
} elseif (!isset($this->pendingSelects[$pendingid])) {
qa_fatal_error('Pending query was never set up: ' . $pendingid);
}
if (!isset($this->pendingResults[$pendingid])) {
$this->selectWithPending();
}
return $this->pendingResults[$pendingid];
}
/**
* Remove the results of queued SELECT query identified by $pendingid if it has already been run. This means it will
* run again if its results are requested via qa_db_get_pending_result()
* @param string $pendingid
*/
public function flushPendingResult($pendingid)
{
unset($this->pendingResults[$pendingid]);
}
/**
* Modify a selectspec to count the number of items. This assumes the original selectspec does not have a LIMIT clause.
* Currently works with message inbox/outbox functions and user-flags function.
* @param array $selectspec
* @return array
*/
public function selectspecWithCount($selectspec)
{
$selectspec['columns'] = array('count' => 'COUNT(*)');
$selectspec['single'] = true;
unset($selectspec['arraykey']);
return $selectspec;
}
/**
* Post-process $outresult according to $selectspec, applying 'sortasc', 'sortdesc', 'arrayvalue' and 'single'. * Post-process $outresult according to $selectspec, applying 'sortasc', 'sortdesc', 'arrayvalue' and 'single'.
* @param array $outresult * @param array $outresult
* @param array $selectspec * @param array $selectspec
......
...@@ -16,14 +16,15 @@ ...@@ -16,14 +16,15 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
namespace Q2A\App; namespace Q2A\Util;
use Q2A\Exceptions\FatalErrorException; /**
* Simple object store.
class Container */
class Set
{ {
/** @var array */ /** @var array */
protected $services = array(); protected $items = [];
/** /**
* Bind an object to a key. * Bind an object to a key.
...@@ -32,21 +33,20 @@ class Container ...@@ -32,21 +33,20 @@ class Container
*/ */
public function set($key, $object) public function set($key, $object)
{ {
$this->services[$key] = $object; $this->items[$key] = $object;
} }
/** /**
* Return an object assigned to the given key. If the key is not found an exception is thrown. * Return an object assigned to the given key, otherwise null.
* @throws FatalErrorException
* @param string $key The key to look for * @param string $key The key to look for
* @return mixed * @return mixed
*/ */
public function get($key) public function get($key)
{ {
if (isset($this->services[$key])) { if (isset($this->items[$key])) {
return $this->services[$key]; return $this->items[$key];
} }
throw new FatalErrorException(sprintf('Key "%s" not found in container', $key)); return null;
} }
} }
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