ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilDBPdoManager.php
Go to the documentation of this file.
1 <?php
2 
25 {
26 
30  protected $pdo;
34  protected $db_instance;
35 
36 
43  public function __construct(\PDO $pdo, ilDBPdo $db_instance)
44  {
45  $this->pdo = $pdo;
46  $this->db_instance = $db_instance;
47  }
48 
49 
53  protected $query_utils;
54 
55 
59  public function getQueryUtils()
60  {
61  if (!$this->query_utils) {
62  $this->query_utils = new ilMySQLQueryUtils($this->db_instance);
63  }
64 
65  return $this->query_utils;
66  }
67 
68 
72  public function getDBInstance()
73  {
74  return $this->db_instance;
75  }
76 
77 
82  public function listTables($database = null)
83  {
84  $str = 'SHOW TABLES ' . ($database ? ' IN ' . $database : '');
85  $r = $this->pdo->query($str);
86  $tables = array();
87 
88  $sequence_identifier = "_seq";
89  while ($data = $r->fetchColumn()) {
90  if (!preg_match("/{$sequence_identifier}$/um", $data)) {
91  $tables[] = $data;
92  }
93  }
94 
95  return $tables;
96  }
97 
98 
104  protected function fixSequenceName($sqn, $check = false)
105  {
106  $seq_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBConstants::SEQUENCE_FORMAT) . '$/i';
107  $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
108  if ($seq_name && !strcasecmp($sqn, $this->db_instance->getSequenceName($seq_name))) {
109  return $seq_name;
110  }
111  if ($check) {
112  return false;
113  }
114 
115  return $sqn;
116  }
117 
118 
123  public function listSequences($database = null)
124  {
125  $query = "SHOW TABLES";
126  if (!is_null($database)) {
127  $query .= " FROM $database";
128  }
129 
130  $res = $this->db_instance->query($query);
131 
132  $result = array();
133  while ($table_name = $this->db_instance->fetchAssoc($res)) {
134  if ($sqn = $this->fixSequenceName(reset($table_name), true)) {
135  $result[] = $sqn;
136  }
137  }
138  if ($this->db_instance->options['portability'] ?? null) {
139  $result = array_map(($this->db_instance->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
140  }
141 
142  return $result;
143  }
144 
145 
153  public function createConstraint($table, $name, $definition)
154  {
155  $db = $this->db_instance;
156 
157  $table = $db->quoteIdentifier($table, true);
158  $name = $db->quoteIdentifier($db->getIndexName($name), true);
159  $query = "ALTER TABLE $table ADD CONSTRAINT $name";
160  if (!empty($definition['primary'])) {
161  $query .= ' PRIMARY KEY';
162  } elseif (!empty($definition['unique'])) {
163  $query .= ' UNIQUE';
164  }
165  $fields = array();
166  foreach (array_keys($definition['fields']) as $field) {
167  $fields[] = $db->quoteIdentifier($field, true);
168  }
169  $query .= ' (' . implode(', ', $fields) . ')';
170 
171  return $this->pdo->exec($query);
172  }
173 
174 
181  public function createSequence($seq_name, $start = 1, $options = array())
182  {
183  $sequence_name = $this->db_instance->quoteIdentifier($this->db_instance->getSequenceName($seq_name));
184  $seqcol_name = $this->db_instance->quoteIdentifier(ilDBConstants::SEQUENCE_COLUMNS_NAME);
185 
186  $options_strings = array();
187 
188  if (!empty($options['comment'])) {
189  $options_strings['comment'] = 'COMMENT = ' . $this->db_instance->quote($options['comment'], 'text');
190  }
191 
192  if (!empty($options['charset'])) {
193  $options_strings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
194  if (!empty($options['collate'])) {
195  $options_strings['charset'] .= ' COLLATE ' . $options['collate'];
196  }
197  }
198 
199  $type = false;
200  if (!empty($options['type'])) {
201  $type = $options['type'];
202  }
203  if ($type) {
204  $options_strings[] = "ENGINE = $type";
205  }
206 
207  $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
208 
209  if (!empty($options_strings)) {
210  $query .= ' ' . implode(' ', $options_strings);
211  }
212  $this->pdo->exec($query);
213 
214  if ($start == 1) {
215  return true;
216  }
217 
218  $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (" . ($start - 1) . ')';
219  $this->pdo->exec($query);
220 
221  return true;
222  }
223 
224 
232  public function alterTable($name, $changes, $check)
233  {
234  $db = $this->db_instance;
235 
236  foreach ($changes as $change_name => $change) {
237  switch ($change_name) {
238  case 'add':
239  case 'remove':
240  case 'change':
241  case 'rename':
242  case 'name':
243  break;
244  default:
245  throw new ilDatabaseException('change type "' . $change_name . '" not yet supported');
246  }
247  }
248 
249  if ($check) {
250  return true;
251  }
252 
253  $query = '';
254  if (!empty($changes['name'])) {
255  $change_name = $db->quoteIdentifier($changes['name']);
256  $query .= 'RENAME TO ' . $change_name;
257  }
258 
259  if (!empty($changes['add']) && is_array($changes['add'])) {
260  foreach ($changes['add'] as $field_name => $field) {
261  if ($query) {
262  $query .= ', ';
263  }
264  $query .= 'ADD ' . $db->getFieldDefinition()->getDeclaration($field['type'], $field_name, $field);
265  }
266  }
267 
268  if (!empty($changes['remove']) && is_array($changes['remove'])) {
269  foreach ($changes['remove'] as $field_name => $field) {
270  if ($query) {
271  $query .= ', ';
272  }
273  $field_name = $db->quoteIdentifier($field_name);
274  $query .= 'DROP ' . $field_name;
275  }
276  }
277 
278  $rename = array();
279  if (!empty($changes['rename']) && is_array($changes['rename'])) {
280  foreach ($changes['rename'] as $field_name => $field) {
281  $rename[$field['name']] = $field_name;
282  }
283  }
284 
285  if (!empty($changes['change']) && is_array($changes['change'])) {
286  foreach ($changes['change'] as $field_name => $field) {
287  if ($query) {
288  $query .= ', ';
289  }
290  if (isset($rename[$field_name])) {
291  $old_field_name = $rename[$field_name];
292  unset($rename[$field_name]);
293  } else {
294  $old_field_name = $field_name;
295  }
296  $old_field_name = $db->quoteIdentifier($old_field_name);
297  $query .= "CHANGE $old_field_name " . $this->db_instance->getFieldDefinition()
298  ->getDeclaration($field['definition']['type'], $field_name, $field['definition']);
299  }
300  }
301 
302  if (!empty($rename) && is_array($rename)) {
303  foreach ($rename as $rename_name => $renamed_field) {
304  if ($query) {
305  $query .= ', ';
306  }
307  $field = $changes['rename'][$renamed_field];
308  $renamed_field = $db->quoteIdentifier($renamed_field);
309  $query .= 'CHANGE ' . $renamed_field . ' ' . $this->db_instance->getFieldDefinition()
310  ->getDeclaration($field['definition']['type'], $field['name'], $field['definition']);
311  }
312  }
313 
314  if (!$query) {
315  return true;
316  }
317 
318  $name = $db->quoteIdentifier($name, true);
319 
320  $statement = "ALTER TABLE $name $query";
321 
322  return $this->pdo->exec($statement);
323  }
324 
325 
332  public function createTable($name, $fields, $options = array())
333  {
334  $options['type'] = $this->db_instance->getStorageEngine();
335 
336  return $this->pdo->exec($this->getQueryUtils()->createTable($name, $fields, $options));
337  }
338 
339 
340 
341 
342 
343  //
344  // ilDBPdoManagerInterface
345  //
350  public function getIndexName($idx)
351  {
352  return $this->db_instance->getIndexName($idx);
353  }
354 
355 
360  public function getSequenceName($sqn)
361  {
362  return $this->db_instance->getSequenceName($sqn);
363  }
364 
365 
371  public function listTableFields($table)
372  {
373  $table = $this->db_instance->quoteIdentifier($table);
374  $query = "SHOW COLUMNS FROM $table";
375  $result = $this->db_instance->query($query);
376  $return = array();
377  while ($data = $this->db_instance->fetchObject($result)) {
378  $return[] = $data->Field;
379  }
380 
381  return $return;
382  }
383 
384 
390  public function listTableConstraints($table)
391  {
392  $key_name = 'Key_name';
393  $non_unique = 'Non_unique';
394 
395  $db = $this->getDBInstance();
396  if ($db->options['portability'] ?? false) {
397  if (($db->options['field_case'] ?? null) == CASE_LOWER) {
398  $key_name = strtolower($key_name);
399  $non_unique = strtolower($non_unique);
400  } else {
401  $key_name = strtoupper($key_name);
402  $non_unique = strtoupper($non_unique);
403  }
404  }
405 
406  $table = $this->db_instance->quoteIdentifier($table);
407  $query = "SHOW INDEX FROM $table";
408  $result_set = $this->db_instance->query($query);
409 
410  $result = array();
411  while ($index_data = $this->db_instance->fetchAssoc($result_set)) {
412  if (!$index_data[$non_unique]) {
413  if ($index_data[$key_name] !== 'PRIMARY') {
414  $index = $this->fixIndexName($index_data[$key_name]);
415  } else {
416  $index = 'PRIMARY';
417  }
418  if (!empty($index)) {
419  $index = strtolower($index);
420  $result[$index] = true;
421  }
422  }
423  }
424 
425  if ($this->db_instance->options['portability'] ?? false) {
426  $result = array_change_key_case($result, $this->db_instance->options['field_case'] ?? null);
427  }
428 
429  return array_keys($result);
430  }
431 
432 
438  public function listTableIndexes($table)
439  {
440  $key_name = 'Key_name';
441  $non_unique = 'Non_unique';
442  if ($this->db_instance->options['portability'] ?? null) {
443  if ($this->db_instance->options['field_case'] == CASE_LOWER) {
444  $key_name = strtolower($key_name);
445  $non_unique = strtolower($non_unique);
446  } else {
447  $key_name = strtoupper($key_name);
448  $non_unique = strtoupper($non_unique);
449  }
450  }
451 
452  $table = $this->db_instance->quoteIdentifier($table);
453  $query = "SHOW INDEX FROM $table";
454  $result_set = $this->db_instance->query($query);
455  $indexes = array();
456  while ($index_data = $this->db_instance->fetchAssoc($result_set)) {
457  $indexes[] = $index_data;
458  }
459  $result = array();
460  foreach ($indexes as $index_data) {
461  if ($index_data[$non_unique] && ($index = $this->fixIndexName($index_data[$key_name]))) {
462  $result[$index] = true;
463  }
464  }
465 
466  if ($this->db_instance->options['portability'] ?? null) {
467  $result = array_change_key_case($result, $this->db_instance->options['field_case']);
468  }
469 
470  return array_keys($result);
471  }
472 
473 
478  protected function fixIndexName($idx)
479  {
480  $idx_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBPdoFieldDefinition::INDEX_FORMAT) . '$/i';
481  $idx_name = preg_replace($idx_pattern, '\\1', $idx);
482  if ($idx_name && !strcasecmp($idx, $this->db_instance->getIndexName($idx_name))) {
483  return $idx_name;
484  }
485 
486  return $idx;
487  }
488 
489 
496  public function createIndex($table, $name, $definition)
497  {
498  $table = $this->db_instance->quoteIdentifier($table, true);
499  $name = $this->db_instance->quoteIdentifier($this->db_instance->getIndexName($name), true);
500  $query = "CREATE INDEX $name ON $table";
501  $fields = array();
502  foreach ($definition['fields'] as $field => $fieldinfo) {
503  if (!empty($fieldinfo['length'])) {
504  $fields[] = $this->db_instance->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')';
505  } else {
506  $fields[] = $this->db_instance->quoteIdentifier($field, true);
507  }
508  }
509  $query .= ' (' . implode(', ', $fields) . ')';
510 
511  return $this->pdo->exec($query);
512  }
513 
514 
520  public function dropIndex($table, $name)
521  {
522  $table = $this->db_instance->quoteIdentifier($table, true);
523  $name = $this->db_instance->quoteIdentifier($this->db_instance->getIndexName($name), true);
524 
525  return $this->pdo->exec("DROP INDEX $name ON $table");
526  }
527 
528 
533  public function dropSequence($table_name)
534  {
535  $sequence_name = $this->db_instance->quoteIdentifier($this->db_instance->getSequenceName($table_name));
536 
537  return $this->pdo->exec("DROP TABLE $sequence_name");
538  }
539 
540 
548  public function getTableCreationQuery($name, $fields, $options = array())
549  {
550  return $this->getQueryUtils()->createTable($name, $fields, $options);
551  }
552 
553 
560  public function dropConstraint($table, $name, $primary = false)
561  {
562  $db = $this->getDBInstance();
563  $table = $db->quoteIdentifier($table, true);
564  if ($primary || strtolower($name) == 'primary') {
565  $query = "ALTER TABLE $table DROP PRIMARY KEY";
566  } else {
567  $name = $db->quoteIdentifier($db->getIndexName($name), true);
568  $query = "ALTER TABLE $table DROP INDEX $name";
569  }
570 
571  return $this->pdo->exec($query);
572  }
573 
574 
578  public function dropTable($name)
579  {
580  $db = $this->getDBInstance();
581 
582  $name = $db->quoteIdentifier($name, true);
583 
584  return $db->manipulate("DROP TABLE $name");
585  }
586 }
alterTable($name, $changes, $check)
listTables($database=null)
listSequences($database=null)
$data
Definition: storeScorm.php:23
$result
Interface ilDBManager.
$type
fixSequenceName($sqn, $check=false)
dropTable($name)
Table-name mixed
dropSequence($table_name)
getTableCreationQuery($name, $fields, $options=array())
Interface ilDBPdoManagerInterface.
Class ilDatabaseException.
createConstraint($table, $name, $definition)
createTable($name, $fields, $options=array())
$index
Definition: metadata.php:128
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if($format !==null) $name
Definition: metadata.php:230
foreach($_POST as $key=> $value) $res
dropConstraint($table, $name, $primary=false)
$query
createIndex($table, $name, $definition)
Class ilMySQLQueryUtils.
__construct(\PDO $pdo, ilDBPdo $db_instance)
ilDBPdoManager constructor.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
dropIndex($table, $name)
createSequence($seq_name, $start=1, $options=array())