ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilDBPdoMySQL.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
24 abstract class ilDBPdoMySQL extends ilDBPdo
25 {
29  protected array $modes = [
30  'STRICT_TRANS_TABLES',
31  'STRICT_ALL_TABLES',
32  'IGNORE_SPACE',
33  'NO_ZERO_IN_DATE',
34  'NO_ZERO_DATE',
35  'ERROR_FOR_DIVISION_BY_ZERO',
36  'NO_ENGINE_SUBSTITUTION',
37  ];
38 
39  public function supportsTransactions(): bool
40  {
41  return false;
42  }
43 
44  public function initHelpers(): void
45  {
46  $this->manager = new ilDBPdoManager($this->pdo, $this);
47  $this->reverse = new ilDBPdoReverse($this->pdo, $this);
48  $this->field_definition = new ilDBPdoMySQLFieldDefinition($this);
49  }
50 
51  protected function initSQLMode(): void
52  {
53  $this->pdo->exec("SET SESSION sql_mode = '" . implode(",", $this->modes) . "';");
54  }
55 
56  public function supportsEngineMigration(): bool
57  {
58  return true;
59  }
60 
64  protected function getAdditionalAttributes(): array
65  {
66  return array(
67  PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
68  PDO::ATTR_TIMEOUT => 300 * 60,
69  );
70  }
71 
72  public function migrateTableToEngine(string $table_name, string $engine = ilDBConstants::MYSQL_ENGINE_INNODB): void
73  {
74  try {
75  $this->pdo->exec("ALTER TABLE {$table_name} ENGINE={$engine}");
76  if ($this->sequenceExists($table_name)) {
77  $this->pdo->exec("ALTER TABLE {$table_name}_seq ENGINE={$engine}");
78  }
79  } catch (PDOException $e) {
80  throw new ilDatabaseException($e->getMessage());
81  }
82  }
83 
87  public function migrateAllTablesToEngine(string $engine = ilDBConstants::MYSQL_ENGINE_INNODB): array
88  {
89  $engines = $this->queryCol('SHOW ENGINES');
90  if (!in_array($engine, $engines, true)) {
91  return [];
92  }
93  $errors = [];
94  $tables = $this->listTables();
95  array_walk($tables, function (string $table_name) use (&$errors, $engine): void {
96  try {
97  $this->pdo->exec("ALTER TABLE $table_name ENGINE=$engine");
98  if ($this->sequenceExists($table_name)) {
99  $this->pdo->exec("ALTER TABLE {$table_name}_seq ENGINE=$engine");
100  }
101  } catch (Exception $e) {
102  $errors[$table_name] = $e->getMessage();
103  }
104  });
105 
106  return $errors;
107  }
108 
109  public function migrateTableCollation(
110  string $table_name,
111  string $collation = ilDBConstants::MYSQL_COLLATION_UTF8MB4
112  ): bool {
113  $collation_split = explode("_", $collation);
114  $character = $collation_split[0] ?? 'utf8mb4';
115  $collate = $collation;
116  $q = "ALTER TABLE {$this->quoteIdentifier($table_name)} CONVERT TO CHARACTER SET {$character} COLLATE {$collate};";
117  try {
118  $this->pdo->exec($q);
119  } catch (PDOException $e) {
120  return false;
121  }
122  return true;
123  }
124 
128  public function migrateAllTablesToCollation(string $collation = ilDBConstants::MYSQL_COLLATION_UTF8MB4): array
129  {
131  $errors = [];
132  foreach ($manager->listTables() as $table_name) {
133  if (!$this->migrateTableCollation($table_name, $collation)) {
134  $errors[] = $table_name;
135  }
136  }
137 
138  return $errors;
139  }
140 
144  public function supportsCollationMigration(): bool
145  {
146  return true;
147  }
148 
149  public function nextId(string $table_name): int
150  {
151  $sequence_name = $this->quoteIdentifier($this->getSequenceName($table_name), true);
152  $seqcol_name = $this->quoteIdentifier('sequence');
153  $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
154  try {
155  $this->pdo->exec($query);
156  } catch (PDOException $e) {
157  // no such table check
158  }
159 
160  $result = $this->query('SELECT LAST_INSERT_ID() AS next');
161  $value = $result->fetchObject()->next;
162 
163  if (is_numeric($value)) {
164  $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
165  $this->pdo->exec($query);
166  }
167 
168  return (int) $value;
169  }
170 
174  public function doesCollationSupportMB4Strings(): bool
175  {
176  // Currently ILIAS does not support utf8mb4, after that ilDB could check like this:
177  // static $supported;
178  // if (!isset($supported)) {
179  // $q = "SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = %s;";
180  // $res = $this->queryF($q, ['text'], [$this->getDbname()]);
181  // $data = $this->fetchObject($res);
182  // $supported = ($data->default_character_set_name === 'utf8mb4');
183  // }
184 
185  return false;
186  }
187 }
migrateAllTablesToCollation(string $collation=ilDBConstants::MYSQL_COLLATION_UTF8MB4)
$errors
Definition: imgupload.php:65
query(string $query)
Class ilDBPdoMySQL.
getSequenceName(string $table_name)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class pdoDB.
loadModule(string $module)
migrateAllTablesToEngine(string $engine=ilDBConstants::MYSQL_ENGINE_INNODB)
nextId(string $table_name)
$query
ilDBPdoManager $manager
listTables(?string $database=null)
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...
queryCol(string $query, int $type=PDO::FETCH_ASSOC, int $colnum=0)
migrateTableCollation(string $table_name, string $collation=ilDBConstants::MYSQL_COLLATION_UTF8MB4)
migrateTableToEngine(string $table_name, string $engine=ilDBConstants::MYSQL_ENGINE_INNODB)
sequenceExists(string $sequence)