ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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  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() {
184  return $this->isolation_level;
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 }
Class ilAtomQuery.
static checkAnomaly($anomalie)
Class ilTableLock.
Interface ilDBInterface.
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.
Create styles array
The data for the language used.
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)
static isThereRiskThat($isolation_level, $anomaly)
replaceQueryCallable(callable $query)
__construct(ilDBInterface $ilDBInstance, $isolation_level=ilAtomQuery::ISOLATION_SERIALIZABLE)
ilAtomQuery constructor.