ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilAtomQueryBase.php
Go to the documentation of this file.
1 <?php
2 require_once('./Services/Database/interfaces/interface.ilAtomQuery.php');
3 require_once('./Services/Database/classes/Atom/class.ilTableLock.php');
4 
13 abstract 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  {
79  static::checkIsolationLevel($isolation_level);
80  $this->ilDBInstance = $ilDBInstance;
81  $this->isolation_level = $isolation_level;
82  }
83 
84  //
85  //
86  //
90  public function getRisks()
91  {
92  return static::getPossibleAnomalies($this->getIsolationLevel());
93  }
94 
95 
107  public function addTableLock($table_name)
108  {
109  $ilTableLock = new ilTableLock($table_name, $this->ilDBInstance);
110  $ilTableLock->setLockLevel($this->getDeterminedLockLevel());
111  $this->tables[] = $ilTableLock;
112 
113  return $ilTableLock;
114  }
115 
116 
120  protected function getDeterminedLockLevel()
121  {
122  switch ($this->getIsolationLevel()) {
125  // Currently only ISOLATION_SERIALIZABLE is allowed
126  }
127 
129  }
130 
131 
152  public function addQueryCallable(callable $query)
153  {
154  if ($this->query) {
156  }
157  if (!$this->checkCallable($query)) {
159  }
160  $this->query = $query;
161  }
162 
163 
168  public function replaceQueryCallable(callable $query)
169  {
170  if (!$this->checkCallable($query)) {
172  }
173  $this->query = $query;
174  }
175 
176 
182  abstract public function run();
183  //
184  //
185  //
189  public function getIsolationLevel()
190  {
191  return $this->isolation_level;
192  }
193 
194 
201  public static function isThereRiskThat($isolation_level, $anomaly)
202  {
203  static::checkIsolationLevel($isolation_level);
204  static::checkAnomaly($anomaly);
205 
206  return in_array($anomaly, static::getPossibleAnomalies($isolation_level));
207  }
208 
209 
214  public static function getPossibleAnomalies($isolation_level)
215  {
216  static::checkIsolationLevel($isolation_level);
217 
218  return self::$anomalies_map[$isolation_level];
219  }
220 
221 
226  public static function checkIsolationLevel($isolation_level)
227  {
228  // The following Isolations are currently not supported
229  if (in_array($isolation_level, array(
233  ))) {
235  }
236  // Check if a available Isolation level is selected
237  if (!in_array($isolation_level, self::$available_isolations_levels)) {
239  }
240  }
241 
242 
247  public static function checkAnomaly($anomalie)
248  {
249  if (!in_array($anomalie, self::$possible_anomalies)) {
251  }
252  }
253 
254 
258  protected function checkQueries()
259  {
260  if ((is_array($this->query) && 0 === count($this->query)) && !($this->query instanceof \Traversable)) {
262  }
263 
264  foreach ($this->query as $query) {
265  if (!$this->checkCallable($query)) {
267  }
268  }
269  }
270 
271 
276  public function checkCallable(callable $query)
277  {
278  if (!is_callable($query)) {
279  return false; // Won't be triggered sidn type-hinting already checks this
280  }
281  if (is_array($query)) {
282  return false;
283  }
284  if (is_string($query)) {
285  return false;
286  }
287  $classname = get_class($query);
288  $is_a_closure = $classname == 'Closure';
289  if (!$is_a_closure) {
290  $ref = new ReflectionClass($query);
291  foreach ($ref->getMethods() as $method) {
292  if ($method->getName() == '__invoke') {
293  return true;
294  }
295  }
296 
297  return false;
298  }
299  if ($is_a_closure) {
300  $ref = new ReflectionFunction($query);
301  $parameters = $ref->getParameters();
302  if (count($parameters) !== 1) {
303  return false;
304  }
305  $reflectionClass = $parameters[0]->getClass();
306  if ($reflectionClass && $reflectionClass->getName() == 'ilDBInterface') {
307  return true;
308  }
309 
310  return false;
311  }
312 
313  return true;
314  }
315 
316 
320  protected function hasWriteLocks()
321  {
322  $has_write_locks = false;
326  foreach ($this->tables as $table) {
327  if ($table->getLockLevel() == ilAtomQuery::LOCK_WRITE) {
328  $has_write_locks = true;
329  }
330  }
331 
332  return $has_write_locks;
333  }
334 
335 
339  protected function runQueries()
340  {
342  $query($this->ilDBInstance);
343  }
344 
345 
349  protected function checkBeforeRun()
350  {
351  $this->checkQueries();
352 
353  if ($this->hasWriteLocks() && $this->getIsolationLevel() != ilAtomQuery::ISOLATION_SERIALIZABLE) {
355  }
356 
357  if (count($this->tables) === 0) {
359  }
360  }
361 }
Class ilAtomQuery.
static checkAnomaly($anomalie)
Class ilTableLock.
run()
Fire your Queries.
addQueryCallable(callable $query)
All action on the database during this isolation has to be passed as Callable to ilAtomQuery.
Class ilAtomQueryException.
Interface ilAtomQuery.
addTableLock($table_name)
Add table-names which are influenced by your queries, MyISAm has to lock those tables.
checkCallable(callable $query)
static getPossibleAnomalies($isolation_level)
static checkIsolationLevel($isolation_level)
if(empty($password)) $table
Definition: pwgen.php:24
static isThereRiskThat($isolation_level, $anomaly)
replaceQueryCallable(callable $query)
__construct(ilDBInterface $ilDBInstance, $isolation_level=ilAtomQuery::ISOLATION_SERIALIZABLE)
ilAtomQuery constructor.