ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilAtomQueryBase.php
Go to the documentation of this file.
1<?php
2require_once('./Services/Database/interfaces/interface.ilAtomQuery.php');
3require_once('./Services/Database/classes/Atom/class.ilTableLock.php');
4
13abstract class ilAtomQueryBase implements ilAtomQuery {
14
15 const ITERATIONS = 10;
19 protected static $available_isolations_levels = array(
24 );
28 protected static $possible_anomalies = array(
33 );
37 protected static $anomalies_map = array(
43 ),
47 ),
50 ),
52 );
60 protected $tables = array();
64 protected $query = null;
68 protected $ilDBInstance;
69
70
78 static::checkIsolationLevel($isolation_level);
79 $this->ilDBInstance = $ilDBInstance;
80 $this->isolation_level = $isolation_level;
81 }
82
83 //
84 //
85 //
89 public function getRisks() {
90 return static::getPossibleAnomalies($this->getIsolationLevel());
91 }
92
93
105 public function addTableLock($table_name) {
106 $ilTableLock = new ilTableLock($table_name, $this->ilDBInstance);
107 $ilTableLock->setLockLevel($this->getDeterminedLockLevel());
108 $this->tables[] = $ilTableLock;
109
110 return $ilTableLock;
111 }
112
113
117 protected function getDeterminedLockLevel() {
118 switch ($this->getIsolationLevel()) {
121 // Currently only ISOLATION_SERIALIZABLE is allowed
122 }
123
125 }
126
127
148 public function addQueryCallable(callable $query) {
149 if ($this->query) {
151 }
152 if (!$this->checkCallable($query)) {
154 }
155 $this->query = $query;
156 }
157
158
163 public function replaceQueryCallable(callable $query) {
164 if (!$this->checkCallable($query)) {
166 }
167 $this->query = $query;
168 }
169
170
176 abstract public function run();
177 //
178 //
179 //
183 public function getIsolationLevel() {
185 }
186
187
194 public static function isThereRiskThat($isolation_level, $anomaly) {
195 static::checkIsolationLevel($isolation_level);
196 static::checkAnomaly($anomaly);
197
198 return in_array($anomaly, static::getPossibleAnomalies($isolation_level));
199 }
200
201
206 public static function getPossibleAnomalies($isolation_level) {
207 static::checkIsolationLevel($isolation_level);
208
209 return self::$anomalies_map[$isolation_level];
210 }
211
212
217 public static function checkIsolationLevel($isolation_level) {
218 // The following Isolations are currently not supported
219 if (in_array($isolation_level, array(
223 ))) {
225 }
226 // Check if a available Isolation level is selected
227 if (!in_array($isolation_level, self::$available_isolations_levels)) {
229 }
230 }
231
232
237 public static function checkAnomaly($anomalie) {
238 if (!in_array($anomalie, self::$possible_anomalies)) {
240 }
241 }
242
243
247 protected function checkQueries() {
248 if (count($this->query) == 0) {
250 }
251 foreach ($this->query as $query) {
252 if (!$this->checkCallable($query)) {
254 }
255 }
256 }
257
258
263 public function checkCallable(callable $query) {
264 if (!is_callable($query)) {
265 return false; // Won't be triggered sidn type-hinting already checks this
266 }
267 if (is_array($query)) {
268 return false;
269 }
270 if (is_string($query)) {
271 return false;
272 }
273 $classname = get_class($query);
274 $is_a_closure = $classname == 'Closure';
275 if (!$is_a_closure) {
276 $ref = new ReflectionClass($query);
277 foreach ($ref->getMethods() as $method) {
278 if ($method->getName() == '__invoke') {
279 return true;
280 }
281 }
282
283 return false;
284 }
285 if ($is_a_closure) {
286 $ref = new ReflectionFunction($query);
287 $parameters = $ref->getParameters();
288 if (count($parameters) !== 1) {
289 return false;
290 }
291 $reflectionClass = $parameters[0]->getClass();
292 if ($reflectionClass && $reflectionClass->getName() == 'ilDBInterface') {
293 return true;
294 }
295
296 return false;
297 }
298
299 return true;
300 }
301
302
306 protected function hasWriteLocks() {
307 $has_write_locks = false;
311 foreach ($this->tables as $table) {
312 if ($table->getLockLevel() == ilAtomQuery::LOCK_WRITE) {
313 $has_write_locks = true;
314 }
315 }
316
317 return $has_write_locks;
318 }
319
320
324 protected function runQueries() {
326 $query($this->ilDBInstance);
327 }
328
329
333 protected function checkBeforeRun() {
334 $this->checkQueries();
335
336 if ($this->hasWriteLocks() && $this->getIsolationLevel() != ilAtomQuery::ISOLATION_SERIALIZABLE) {
338 }
339
340 if (count($this->tables) === 0) {
342 }
343 }
344}
An exception for terminatinating execution or to throw for unit testing.
Class ilAtomQuery.
addTableLock($table_name)
Add table-names which are influenced by your queries, MyISAm has to lock those tables.
static getPossibleAnomalies($isolation_level)
__construct(ilDBInterface $ilDBInstance, $isolation_level=ilAtomQuery::ISOLATION_SERIALIZABLE)
ilAtomQuery constructor.
static checkAnomaly($anomalie)
static checkIsolationLevel($isolation_level)
addQueryCallable(callable $query)
All action on the database during this isolation has to be passed as Callable to ilAtomQuery.
checkCallable(callable $query)
static isThereRiskThat($isolation_level, $anomaly)
run()
Fire your Queries.
replaceQueryCallable(callable $query)
Class ilAtomQueryException.
Class ilTableLock.
Interface ilAtomQuery.
Interface ilDBInterface.