ILIAS  release_8 Revision v8.24
class.ilDBPdoManager.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
26{
27 protected \PDO $pdo;
28 protected \ilDBPdo $db_instance;
29 protected ?\ilQueryUtils $query_utils = null;
30
34 public function __construct(\PDO $pdo, ilDBPdo $db_instance)
35 {
36 $this->pdo = $pdo;
37 $this->db_instance = $db_instance;
38 }
39
40 public function getQueryUtils(): \ilQueryUtils
41 {
42 if ($this->query_utils === null) {
43 $this->query_utils = new ilMySQLQueryUtils($this->db_instance);
44 }
45
46 return $this->query_utils;
47 }
48
49 public function getDBInstance(): \ilDBPdo
50 {
51 return $this->db_instance;
52 }
53
57 public function listTables(?string $database = null): array
58 {
59 $str = 'SHOW TABLES ' . ($database ? ' IN ' . $database : '');
60 $r = $this->pdo->query($str);
61 $tables = [];
62
63 $sequence_identifier = "_seq";
64 while ($data = $r->fetchColumn()) {
65 if (!preg_match("/$sequence_identifier$/um", $data)) {
66 $tables[] = $data;
67 }
68 }
69
70 return $tables;
71 }
72
73 protected function fixSequenceName(string $sqn, bool $check = false): string
74 {
75 $seq_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBConstants::SEQUENCE_FORMAT) . '$/i';
76 $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
77 if ($seq_name && !strcasecmp($sqn, $this->db_instance->getSequenceName($seq_name))) {
78 return $seq_name;
79 }
80
81 return $sqn;
82 }
83
87 public function listSequences(string $database = null): array
88 {
89 $query = "SHOW TABLES LIKE '%_seq'";
90 if (!is_null($database)) {
91 $query .= " FROM $database";
92 }
93
94 $res = $this->db_instance->query($query);
95
96 $result = array();
97 while ($table_name = $this->db_instance->fetchAssoc($res)) {
98 if ($sqn = $this->fixSequenceName(reset($table_name), true)) {
99 $result[] = $sqn;
100 }
101 }
102 if ($this->db_instance->options['portability'] ?? null) {
103 $result = array_map(
104 ($this->db_instance->options['field_case'] === CASE_LOWER ? 'strtolower' : 'strtoupper'),
105 $result
106 );
107 }
108
109 return $result;
110 }
111
115 public function createConstraint(string $table, string $name, array $definition): bool
116 {
117 $db = $this->db_instance;
118
119 $table = $db->quoteIdentifier($table, true);
120 $name = $db->quoteIdentifier($db->getIndexName($name), true);
121 $query = "ALTER TABLE $table ADD CONSTRAINT $name";
122 if (!empty($definition['primary'])) {
123 $query .= ' PRIMARY KEY';
124 } elseif (!empty($definition['unique'])) {
125 $query .= ' UNIQUE';
126 }
127 $fields = array();
128 foreach (array_keys($definition['fields']) as $field) {
129 $fields[] = $db->quoteIdentifier($field, true);
130 }
131 $query .= ' (' . implode(', ', $fields) . ')';
132
133 return (bool) $this->pdo->exec($query);
134 }
135
136 public function createSequence(string $seq_name, int $start = 1, array $options = []): bool
137 {
138 $sequence_name = $this->db_instance->quoteIdentifier($this->db_instance->getSequenceName($seq_name));
139 $seqcol_name = $this->db_instance->quoteIdentifier(ilDBConstants::SEQUENCE_COLUMNS_NAME);
140
141 $options_strings = array();
142
143 if (!empty($options['comment'])) {
144 $options_strings['comment'] = 'COMMENT = ' . $this->db_instance->quote($options['comment'], 'text');
145 }
146
147 if (!empty($options['charset'])) {
148 $options_strings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
149 if (!empty($options['collate'])) {
150 $options_strings['charset'] .= ' COLLATE ' . $options['collate'];
151 }
152 }
153
154 $type = false;
155 if (!empty($options['type'])) {
156 $type = $options['type'];
157 }
158 if ($type) {
159 $options_strings[] = "ENGINE = $type";
160 }
161
162 $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
163
164 if (!empty($options_strings)) {
165 $query .= ' ' . implode(' ', $options_strings);
166 }
167 $this->pdo->exec($query);
168
169 if ($start == 1) {
170 return true;
171 }
172
173 $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (" . ($start - 1) . ')';
174 $this->pdo->exec($query);
175
176 return true;
177 }
178
182 public function alterTable(string $name, array $changes, bool $check): bool
183 {
184 $db = $this->db_instance;
185
186 foreach (array_keys($changes) as $change_name) {
187 switch ($change_name) {
188 case 'add':
189 case 'remove':
190 case 'change':
191 case 'rename':
192 case 'name':
193 break;
194 default:
195 throw new ilDatabaseException('change type "' . $change_name . '" not yet supported');
196 }
197 }
198
199 if ($check) {
200 return true;
201 }
202
203 $query = '';
204 if (!empty($changes['name'])) {
205 $change_name = $db->quoteIdentifier($changes['name']);
206 $query .= 'RENAME TO ' . $change_name;
207 }
208
209 if (!empty($changes['add']) && is_array($changes['add'])) {
210 foreach ($changes['add'] as $field_name => $field) {
211 if ($query !== '') {
212 $query .= ', ';
213 }
214 $fd = $db->getFieldDefinition();
215 if ($fd !== null) {
216 $query .= 'ADD ' . $fd->getDeclaration($field['type'], $field_name, $field);
217 }
218 }
219 }
220
221 if (!empty($changes['remove']) && is_array($changes['remove'])) {
222 foreach (array_keys($changes['remove']) as $field_name) {
223 if ($query !== '') {
224 $query .= ', ';
225 }
226 $field_name = $db->quoteIdentifier($field_name);
227 $query .= 'DROP ' . $field_name;
228 }
229 }
230
231 $rename = array();
232 if (!empty($changes['rename']) && is_array($changes['rename'])) {
233 foreach ($changes['rename'] as $field_name => $field) {
234 $rename[$field['name']] = $field_name;
235 }
236 }
237
238 if (!empty($changes['change']) && is_array($changes['change'])) {
239 foreach ($changes['change'] as $field_name => $field) {
240 if ($query !== '') {
241 $query .= ', ';
242 }
243 if (isset($rename[$field_name])) {
244 $old_field_name = $rename[$field_name];
245 unset($rename[$field_name]);
246 } else {
247 $old_field_name = $field_name;
248 }
249 $old_field_name = $db->quoteIdentifier($old_field_name);
250 $fd = $this->db_instance->getFieldDefinition();
251 if ($fd !== null) {
252 $query .= "CHANGE $old_field_name " . $fd
253 ->getDeclaration(
254 $field['definition']['type'],
255 $field_name,
256 $field['definition']
257 );
258 }
259 }
260 }
261
262 if (!empty($rename) && is_array($rename)) {
263 foreach ($rename as $renamed_field) {
264 if ($query !== '') {
265 $query .= ', ';
266 }
267 $field = $changes['rename'][$renamed_field];
268 $renamed_field = $db->quoteIdentifier($renamed_field);
269 $fd = $this->db_instance->getFieldDefinition();
270 if ($fd !== null) {
271 $query .= 'CHANGE ' . $renamed_field . ' ' . $fd
272 ->getDeclaration(
273 $field['definition']['type'],
274 $field['name'],
275 $field['definition']
276 );
277 }
278 }
279 }
280
281 if ($query === '') {
282 return true;
283 }
284
285 $name = $db->quoteIdentifier($name, true);
286
287 $statement = "ALTER TABLE $name $query";
288
289 return (bool) $this->pdo->exec($statement);
290 }
291
292 public function createTable(string $name, array $fields, array $options = array()): bool
293 {
294 $options['type'] = $this->db_instance->getStorageEngine();
295
296 return (bool) $this->pdo->exec($this->getQueryUtils()->createTable($name, $fields, $options));
297 }
298
299 public function getIndexName(string $idx): string
300 {
301 return $this->db_instance->getIndexName($idx);
302 }
303
304 public function getSequenceName(string $sqn): string
305 {
306 return $this->db_instance->getSequenceName($sqn);
307 }
308
309 public function listTableFields(string $table): array
310 {
311 $table = $this->db_instance->quoteIdentifier($table);
312 $query = "SHOW COLUMNS FROM $table";
313 $result = $this->db_instance->query($query);
314 $return = array();
315 while ($data = $this->db_instance->fetchObject($result)) {
316 $return[] = $data->Field;
317 }
318
319 return $return;
320 }
321
325 public function listTableConstraints(string $table): array
326 {
327 $key_name = 'Key_name';
328 $non_unique = 'Non_unique';
329
330 $db = $this->getDBInstance();
331 if ($db->options['portability'] ?? null) {
332 if ($db->options['field_case'] == CASE_LOWER) {
333 $key_name = strtolower($key_name);
334 $non_unique = strtolower($non_unique);
335 } else {
336 $key_name = strtoupper($key_name);
337 $non_unique = strtoupper($non_unique);
338 }
339 }
340
341 $table = $this->db_instance->quoteIdentifier($table);
342 $query = "SHOW INDEX FROM $table";
343 $result_set = $this->db_instance->query($query);
344
345 $result = array();
346 while ($index_data = $this->db_instance->fetchAssoc($result_set)) {
347 if (!$index_data[$non_unique]) {
348 $index = $index_data[$key_name] !== 'PRIMARY' ? $this->fixIndexName($index_data[$key_name]) : 'PRIMARY';
349 if (!empty($index)) {
350 $index = strtolower($index);
351 $result[$index] = true;
352 }
353 }
354 }
355
356 if ($this->db_instance->options['portability'] ?? null) {
357 $result = array_change_key_case($result, $this->db_instance->options['field_case']);
358 }
359
360 return array_keys($result);
361 }
362
366 public function listTableIndexes(string $table): array
367 {
368 $key_name = 'Key_name';
369 $non_unique = 'Non_unique';
370 if ($this->db_instance->options['portability'] ?? null) {
371 if ($this->db_instance->options['field_case'] == CASE_LOWER) {
372 $key_name = strtolower($key_name);
373 $non_unique = strtolower($non_unique);
374 } else {
375 $key_name = strtoupper($key_name);
376 $non_unique = strtoupper($non_unique);
377 }
378 }
379
380 $table = $this->db_instance->quoteIdentifier($table);
381 $query = "SHOW INDEX FROM $table";
382 $result_set = $this->db_instance->query($query);
383 $indexes = array();
384 while ($index_data = $this->db_instance->fetchAssoc($result_set)) {
385 $indexes[] = $index_data;
386 }
387 $result = array();
388 foreach ($indexes as $index_data) {
389 if ($index_data[$non_unique] && ($index = $this->fixIndexName($index_data[$key_name]))) {
390 $result[$index] = true;
391 }
392 }
393
394 if ($this->db_instance->options['portability'] ?? null) {
395 $result = array_change_key_case($result, $this->db_instance->options['field_case']);
396 }
397
398 return array_keys($result);
399 }
400
401 protected function fixIndexName(string $idx): string
402 {
403 $idx_pattern = '/^' . preg_replace('/%s/', '([a-z0-9_]+)', ilDBPdoFieldDefinition::INDEX_FORMAT) . '$/i';
404 $idx_name = preg_replace($idx_pattern, '\\1', $idx);
405 if ($idx_name && !strcasecmp($idx, $this->db_instance->getIndexName($idx_name))) {
406 return $idx_name;
407 }
408
409 return $idx;
410 }
411
412 public function createIndex(string $table, string $name, array $definition): bool
413 {
414 $table = $this->db_instance->quoteIdentifier($table, true);
415 $name = $this->db_instance->quoteIdentifier($this->db_instance->getIndexName($name), true);
416 $query = "CREATE INDEX $name ON $table";
417 $fields = array();
418 foreach ($definition['fields'] as $field => $fieldinfo) {
419 if (!empty($fieldinfo['length'])) {
420 $fields[] = $this->db_instance->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')';
421 } else {
422 $fields[] = $this->db_instance->quoteIdentifier($field, true);
423 }
424 }
425 $query .= ' (' . implode(', ', $fields) . ')';
426
427 return (bool) $this->pdo->exec($query);
428 }
429
430 public function dropIndex(string $table, string $name): bool
431 {
432 $table = $this->db_instance->quoteIdentifier($table, true);
433 $name = $this->db_instance->quoteIdentifier($this->db_instance->getIndexName($name), true);
434
435 return (bool) $this->pdo->exec("DROP INDEX $name ON $table");
436 }
437
438 public function dropSequence(string $seq_name): bool
439 {
440 $sequence_name = $this->db_instance->quoteIdentifier($this->db_instance->getSequenceName($seq_name));
441
442 return (bool) $this->pdo->exec("DROP TABLE $sequence_name");
443 }
444
448 public function getTableCreationQuery(string $name, array $fields, array $options = []): string
449 {
450 return $this->getQueryUtils()->createTable($name, $fields, $options);
451 }
452
453 public function dropConstraint(string $table, string $name, bool $primary = false): bool
454 {
455 $db = $this->getDBInstance();
456 $table = $db->quoteIdentifier($table, true);
457 if ($primary || strtolower($name) === 'primary') {
458 $query = "ALTER TABLE $table DROP PRIMARY KEY";
459 } else {
460 $name = $db->quoteIdentifier($db->getIndexName($name), true);
461 $query = "ALTER TABLE $table DROP INDEX $name";
462 }
463
464 return (bool) $this->pdo->exec($query);
465 }
466
467 public function dropTable(string $name): bool
468 {
469 $db = $this->getDBInstance();
470 $name = $db->quoteIdentifier($name, true);
471
472 return (bool) $this->pdo->exec("DROP TABLE $name");
473 }
474}
$check
Definition: buildRTE.php:81
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
alterTable(string $name, array $changes, bool $check)
createTable(string $name, array $fields, array $options=array())
__construct(\PDO $pdo, ilDBPdo $db_instance)
ilDBPdoManager constructor.
dropSequence(string $seq_name)
dropConstraint(string $table, string $name, bool $primary=false)
listTableConstraints(string $table)
ilQueryUtils $query_utils
getTableCreationQuery(string $name, array $fields, array $options=[])
fixSequenceName(string $sqn, bool $check=false)
createConstraint(string $table, string $name, array $definition)
createSequence(string $seq_name, int $start=1, array $options=[])
fixIndexName(string $idx)
listTables(?string $database=null)
dropTable(string $name)
createIndex(string $table, string $name, array $definition)
getIndexName(string $idx)
getSequenceName(string $sqn)
listTableIndexes(string $table)
dropIndex(string $table, string $name)
listSequences(string $database=null)
listTableFields(string $table)
Class pdoDB.
quoteIdentifier(string $identifier, bool $check_option=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$res
Definition: ltiservices.php:69
if($format !==null) $name
Definition: metadata.php:247
$index
Definition: metadata.php:145
$query
$type