3 namespace Org\Mxchange\CoreFramework\Database\Frontend;
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Criteria\Criteria;
7 use Org\Mxchange\CoreFramework\Criteria\Storing\StoreableCriteria;
8 use Org\Mxchange\CoreFramework\Database\Backend\BaseDatabaseBackend;
9 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
10 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
13 * A generic database wrapper
15 * @author Roland Haeder <webmaster@shipsimu.org>
17 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
18 * @license GNU GPL 3.0 or any newer version
19 * @link http://www.shipsimu.org
21 * This program is free software: you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation, either version 3 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 class BaseDatabaseWrapper extends BaseFrameworkSystem {
38 private $cacheInstance = NULL;
41 * Current table name to use
43 private $tableName = 'unknown';
46 * Protected constructor
50 protected function __construct ($class) {
51 // Call parent constructor
52 parent::__construct($class);
54 // Initialize the cache instance
55 $this->initCacheInstance();
59 * Initializes the cache instance with a new object
63 private final function initCacheInstance () {
64 // Is the cache enabled?
65 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
66 // Set the new instance
67 $this->cacheInstance = CacheFactory::getFactory()->createConfiguredCache();
72 * Setter for table name
74 * @param $tableName Name of table name to set
77 protected final function setTableName ($tableName) {
78 $this->tableName = (string) $tableName;
82 * Getter for table name
84 * @return $tableName Name of table name to set
86 protected final function getTableName () {
87 return $this->tableName;
91 * 'Inserts' a data set instance into a local file database folder
93 * @param $dataSetInstance A storeable data set
94 * @param $onlyKeys Only use these keys for a cache key
97 protected function queryInsertDataSet (StoreableCriteria $dataSetInstance, array $onlyKeys = array()) {
98 // Default cache key is NULL
102 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
103 // First get a key suitable for our cache and extend it with this class name
104 $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
105 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
108 // Does this key exists in cache?
109 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
111 $this->cacheInstance->purgeOffset($cacheKey);
114 // Handle it over to the middleware
115 $this->getDatabaseInstance()->queryInsertDataSet($dataSetInstance);
119 * 'Updates' a data set instance with a database layer
121 * @param $dataSetInstance A storeable data set
122 * @param $onlyKeys Only use these keys for a cache key
125 protected function queryUpdateDataSet (StoreableCriteria $dataSetInstance, array $onlyKeys = array()) {
130 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
131 // First get a key suitable for our cache and extend it with this class name
132 $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
133 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
136 // Does this key exists in cache?
137 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
139 $this->cacheInstance->purgeOffset($cacheKey);
142 // Handle it over to the middleware
143 $this->getDatabaseInstance()->queryUpdateDataSet($dataSetInstance);
147 * Getter for index key
149 * @return $indexKey Index key
151 public final function getIndexKey () {
152 return $this->getDatabaseInstance()->getIndexKey();
156 * Getter for last exception
158 * @return $lastException Last exception or NULL if none occured
160 public final function getLastException () {
161 return $this->getDatabaseInstance()->getLastException();
165 * Do a "select" query on the current table with the given search criteria and
166 * store it in cache for later usage
168 * @param $criteriaInstance An instance of a Criteria class
169 * @param $onlyKeys Only use these keys for a cache key
170 * @return $resultInstance An instance of a database result class
172 public function doSelectByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
173 // Default cache key if cache is not enabled
176 // Is the cache enabled?
177 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
178 // First get a key suitable for our cache and extend it with this class name
179 $cacheKey = $this->getCacheKeyByCriteria($criteriaInstance, $onlyKeys);
182 // Does this key exists in cache?
183 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey, BaseDatabaseBackend::RESULT_INDEX_ROWS, 1))) {
185 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Cache used for cacheKey=' . $cacheKey . ':' . print_r($this->cacheInstance->offsetGet($cacheKey), true));
187 // Then use this result
188 $result = $this->cacheInstance->offsetGet($cacheKey);
191 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Quering database, cacheKey=' . $cacheKey);
193 // Now it's time to ask the database layer for this select statement
194 $result = $this->getDatabaseInstance()->doSelectByTableCriteria($this->getTableName(), $criteriaInstance);
195 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: result[]=' . gettype($result));
197 // Cache the result if not null
198 if (!is_null($result)) {
200 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
201 // A valid result has returned from the database layer
202 $this->cacheInstance->offsetSet($cacheKey, $result);
205 // This invalid result must be wrapped
207 BaseDatabaseBackend::RESULT_INDEX_STATUS => 'invalid',
208 BaseDatabaseBackend::RESULT_INDEX_EXCEPTION => $this->getDatabaseInstance()->getLastException()
213 // Create an instance of a CachedDatabaseResult class with the given result
214 // @TODO Minor: Update above comment to e.g. BaseDatabaseResult
215 $resultInstance = ObjectFactory::createObjectByConfiguredName('database_result_class', array($result));
217 // And return the instance
218 return $resultInstance;
222 * Count the numbers of rows we shall receive
224 * @param $criteriaInstance An instance of a Criteria class
225 * @param $onlyKeys Only use these keys for a cache key
226 * @return $numRows Numbers of rows of database entries
228 public function doSelectCountByCriteria (Criteria $criteriaInstance, $onlyKeys = array()) {
229 // Total numbers is -1 so we can distinglish between failed and valid queries
232 // Get the result from above method
233 $resultInstance = $this->doSelectByCriteria($criteriaInstance, $onlyKeys);
235 // Was that query fine?
236 if ($resultInstance->ifStatusIsOkay()) {
237 // Then get the number of rows
238 $numRows = $resultInstance->getAffectedRows();
241 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: numRows=' . $numRows);
249 * Getter for primary key used in wrapped table
251 * @return $primaryKey Primary key used in wrapped table
253 public final function getPrimaryKeyValue () {
254 // Get the table name and a database instance and ask for it
255 $primaryKey = $this->getDatabaseInstance()->getPrimaryKeyOfTable($this->getTableName());
262 * Count rows of this table
264 * @return $count Count of total rows in this table
266 public final function countTotalRows () {
267 // Get the table name and a database instance and ask for it
268 $count = $this->getDatabaseInstance()->countTotalRows($this->getTableName());
275 * Removes non-public data from given array.
277 * @param $data An array with possible non-public data that needs to be removed.
278 * @return $data A cleaned up array with only public data.
280 public function removeNonPublicDataFromArray (array $data) {
281 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: Calling this->getDatabaseInstance()->removeNonPublicDataFromArray(data) ...');
282 $data = $this->getDatabaseInstance()->removeNonPublicDataFromArray($data);
284 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: data[]=' . gettype($data));