ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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))) {
262  }
263  foreach ($this->query as $query) {
264  if (!$this->checkCallable($query)) {
266  }
267  }
268  }
269 
270 
275  public function checkCallable(callable $query)
276  {
277  if (!is_callable($query)) {
278  return false; // Won't be triggered sidn type-hinting already checks this
279  }
280  if (is_array($query)) {
281  return false;
282  }
283  if (is_string($query)) {
284  return false;
285  }
286  $classname = get_class($query);
287  $is_a_closure = $classname == 'Closure';
288  if (!$is_a_closure) {
289  $ref = new ReflectionClass($query);
290  foreach ($ref->getMethods() as $method) {
291  if ($method->getName() == '__invoke') {
292  return true;
293  }
294  }
295 
296  return false;
297  }
298  if ($is_a_closure) {
299  $ref = new ReflectionFunction($query);
300  $parameters = $ref->getParameters();
301  if (count($parameters) !== 1) {
302  return false;
303  }
304  $reflectionClass = $parameters[0]->getClass();
305  if ($reflectionClass && $reflectionClass->getName() == 'ilDBInterface') {
306  return true;
307  }
308 
309  return false;
310  }
311 
312  return true;
313  }
314 
315 
319  protected function hasWriteLocks()
320  {
321  $has_write_locks = false;
325  foreach ($this->tables as $table) {
326  if ($table->getLockLevel() == ilAtomQuery::LOCK_WRITE) {
327  $has_write_locks = true;
328  }
329  }
330 
331  return $has_write_locks;
332  }
333 
334 
338  protected function runQueries()
339  {
341  $query($this->ilDBInstance);
342  }
343 
344 
348  protected function checkBeforeRun()
349  {
350  $this->checkQueries();
351 
352  if ($this->hasWriteLocks() && $this->getIsolationLevel() != ilAtomQuery::ISOLATION_SERIALIZABLE) {
354  }
355 
356  if (count($this->tables) === 0) {
358  }
359  }
360 }
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)
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.