1 | <?php |
||
2 | /* |
||
3 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
4 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
5 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
6 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
7 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
8 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
9 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
10 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
11 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
12 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
13 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
14 | * |
||
15 | * This software consists of voluntary contributions made by many individuals |
||
16 | * and is licensed under the MIT license. For more information, see |
||
17 | * <http://www.doctrine-project.org>. |
||
18 | */ |
||
19 | |||
20 | namespace Doctrine\DBAL\Schema; |
||
21 | |||
22 | use Doctrine\DBAL\Events; |
||
23 | use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs; |
||
24 | use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; |
||
25 | use Doctrine\DBAL\DBALException; |
||
26 | use Doctrine\DBAL\Platforms\AbstractPlatform; |
||
27 | |||
28 | /** |
||
29 | * Base class for schema managers. Schema managers are used to inspect and/or |
||
30 | * modify the database schema/structure. |
||
31 | * |
||
32 | * @author Konsta Vesterinen <[email protected]> |
||
33 | * @author Lukas Smith <[email protected]> (PEAR MDB2 library) |
||
34 | * @author Roman Borschel <[email protected]> |
||
35 | * @author Jonathan H. Wage <[email protected]> |
||
36 | * @author Benjamin Eberlei <[email protected]> |
||
37 | * @since 2.0 |
||
38 | */ |
||
39 | abstract class AbstractSchemaManager |
||
40 | { |
||
41 | /** |
||
42 | * Holds instance of the Doctrine connection for this schema manager. |
||
43 | * |
||
44 | * @var \Doctrine\DBAL\Connection |
||
45 | */ |
||
46 | protected $_conn; |
||
47 | |||
48 | /** |
||
49 | * Holds instance of the database platform used for this schema manager. |
||
50 | * |
||
51 | * @var \Doctrine\DBAL\Platforms\AbstractPlatform |
||
52 | */ |
||
53 | protected $_platform; |
||
54 | |||
55 | /** |
||
56 | * Constructor. Accepts the Connection instance to manage the schema for. |
||
57 | * |
||
58 | * @param \Doctrine\DBAL\Connection $conn |
||
59 | * @param \Doctrine\DBAL\Platforms\AbstractPlatform|null $platform |
||
60 | */ |
||
61 | 38 | public function __construct(\Doctrine\DBAL\Connection $conn, AbstractPlatform $platform = null) |
|
62 | { |
||
63 | 38 | $this->_conn = $conn; |
|
64 | 38 | $this->_platform = $platform ?: $this->_conn->getDatabasePlatform(); |
|
65 | 38 | } |
|
66 | |||
67 | /** |
||
68 | * Returns the associated platform. |
||
69 | * |
||
70 | * @return \Doctrine\DBAL\Platforms\AbstractPlatform |
||
71 | */ |
||
72 | 13 | public function getDatabasePlatform() |
|
73 | { |
||
74 | 13 | return $this->_platform; |
|
75 | } |
||
76 | |||
77 | /** |
||
78 | * Tries any method on the schema manager. Normally a method throws an |
||
79 | * exception when your DBMS doesn't support it or if an error occurs. |
||
80 | * This method allows you to try and method on your SchemaManager |
||
81 | * instance and will return false if it does not work or is not supported. |
||
82 | * |
||
83 | * <code> |
||
84 | * $result = $sm->tryMethod('dropView', 'view_name'); |
||
85 | * </code> |
||
86 | * |
||
87 | * @return mixed |
||
88 | */ |
||
89 | 49 | public function tryMethod() |
|
90 | { |
||
91 | 49 | $args = func_get_args(); |
|
92 | 49 | $method = $args[0]; |
|
93 | 49 | unset($args[0]); |
|
94 | 49 | $args = array_values($args); |
|
95 | |||
96 | try { |
||
97 | 49 | return call_user_func_array([$this, $method], $args); |
|
98 | 14 | } catch (\Exception $e) { |
|
99 | 14 | return false; |
|
100 | } |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Lists the available databases for this connection. |
||
105 | * |
||
106 | * @return array |
||
107 | */ |
||
108 | 1 | public function listDatabases() |
|
109 | { |
||
110 | 1 | $sql = $this->_platform->getListDatabasesSQL(); |
|
111 | |||
112 | $databases = $this->_conn->fetchAll($sql); |
||
113 | |||
114 | return $this->_getPortableDatabasesList($databases); |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Returns a list of all namespaces in the current database. |
||
119 | * |
||
120 | * @return array |
||
121 | */ |
||
122 | public function listNamespaceNames() |
||
123 | { |
||
124 | $sql = $this->_platform->getListNamespacesSQL(); |
||
125 | |||
126 | $namespaces = $this->_conn->fetchAll($sql); |
||
127 | |||
128 | return $this->getPortableNamespacesList($namespaces); |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Lists the available sequences for this connection. |
||
133 | * |
||
134 | * @param string|null $database |
||
135 | * |
||
136 | * @return \Doctrine\DBAL\Schema\Sequence[] |
||
137 | */ |
||
138 | 1 | public function listSequences($database = null) |
|
139 | { |
||
140 | 1 | if (is_null($database)) { |
|
141 | $database = $this->_conn->getDatabase(); |
||
142 | } |
||
143 | 1 | $sql = $this->_platform->getListSequencesSQL($database); |
|
144 | |||
145 | 1 | $sequences = $this->_conn->fetchAll($sql); |
|
146 | |||
147 | 1 | return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); |
|
148 | } |
||
149 | |||
150 | /** |
||
151 | * Lists the columns for a given table. |
||
152 | * |
||
153 | * In contrast to other libraries and to the old version of Doctrine, |
||
154 | * this column definition does try to contain the 'primary' field for |
||
155 | * the reason that it is not portable across different RDBMS. Use |
||
156 | * {@see listTableIndexes($tableName)} to retrieve the primary key |
||
157 | * of a table. We're a RDBMS specifies more details these are held |
||
158 | * in the platformDetails array. |
||
159 | * |
||
160 | * @param string $table The name of the table. |
||
161 | * @param string|null $database |
||
162 | * |
||
163 | * @return \Doctrine\DBAL\Schema\Column[] |
||
164 | */ |
||
165 | 40 | View Code Duplication | public function listTableColumns($table, $database = null) |
166 | { |
||
167 | 40 | if ( ! $database) { |
|
168 | 40 | $database = $this->_conn->getDatabase(); |
|
169 | } |
||
170 | |||
171 | 40 | $sql = $this->_platform->getListTableColumnsSQL($table, $database); |
|
172 | |||
173 | 40 | $tableColumns = $this->_conn->fetchAll($sql); |
|
174 | |||
175 | 40 | return $this->_getPortableTableColumnList($table, $database, $tableColumns); |
|
176 | } |
||
177 | |||
178 | /** |
||
179 | * Lists the indexes for a given table returning an array of Index instances. |
||
180 | * |
||
181 | * Keys of the portable indexes list are all lower-cased. |
||
182 | * |
||
183 | * @param string $table The name of the table. |
||
184 | * |
||
185 | * @return \Doctrine\DBAL\Schema\Index[] |
||
186 | */ |
||
187 | 33 | public function listTableIndexes($table) |
|
188 | { |
||
189 | 33 | $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); |
|
190 | |||
191 | 33 | $tableIndexes = $this->_conn->fetchAll($sql); |
|
192 | |||
193 | 33 | return $this->_getPortableTableIndexesList($tableIndexes, $table); |
|
194 | } |
||
195 | |||
196 | /** |
||
197 | * Returns true if all the given tables exist. |
||
198 | * |
||
199 | * @param array $tableNames |
||
200 | * |
||
201 | * @return boolean |
||
202 | */ |
||
203 | 55 | public function tablesExist($tableNames) |
|
204 | { |
||
205 | 55 | $tableNames = array_map('strtolower', (array) $tableNames); |
|
206 | |||
207 | 55 | return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames()))); |
|
208 | } |
||
209 | |||
210 | /** |
||
211 | * Returns a list of all tables in the current database. |
||
212 | * |
||
213 | * @return array |
||
214 | */ |
||
215 | 58 | public function listTableNames() |
|
216 | { |
||
217 | 58 | $sql = $this->_platform->getListTablesSQL(); |
|
218 | |||
219 | 58 | $tables = $this->_conn->fetchAll($sql); |
|
220 | 58 | $tableNames = $this->_getPortableTablesList($tables); |
|
221 | |||
222 | 58 | return $this->filterAssetNames($tableNames); |
|
223 | } |
||
224 | |||
225 | /** |
||
226 | * Filters asset names if they are configured to return only a subset of all |
||
227 | * the found elements. |
||
228 | * |
||
229 | * @param array $assetNames |
||
230 | * |
||
231 | * @return array |
||
232 | */ |
||
233 | 59 | protected function filterAssetNames($assetNames) |
|
234 | { |
||
235 | 59 | $filterExpr = $this->getFilterSchemaAssetsExpression(); |
|
236 | 59 | if ( ! $filterExpr) { |
|
237 | 58 | return $assetNames; |
|
238 | } |
||
239 | |||
240 | 1 | return array_values( |
|
241 | 1 | array_filter($assetNames, function ($assetName) use ($filterExpr) { |
|
242 | 1 | $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName; |
|
243 | |||
244 | 1 | return preg_match($filterExpr, $assetName); |
|
245 | 1 | }) |
|
246 | ); |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * @return string|null |
||
251 | */ |
||
252 | 59 | protected function getFilterSchemaAssetsExpression() |
|
253 | { |
||
254 | 59 | return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); |
|
255 | } |
||
256 | |||
257 | /** |
||
258 | * Lists the tables for this connection. |
||
259 | * |
||
260 | * @return \Doctrine\DBAL\Schema\Table[] |
||
261 | */ |
||
262 | 5 | public function listTables() |
|
263 | { |
||
264 | 5 | $tableNames = $this->listTableNames(); |
|
265 | |||
266 | 5 | $tables = []; |
|
267 | 5 | foreach ($tableNames as $tableName) { |
|
268 | 4 | $tables[] = $this->listTableDetails($tableName); |
|
269 | } |
||
270 | |||
271 | 5 | return $tables; |
|
272 | } |
||
273 | |||
274 | /** |
||
275 | * @param string $tableName |
||
276 | * |
||
277 | * @return \Doctrine\DBAL\Schema\Table |
||
278 | */ |
||
279 | 29 | public function listTableDetails($tableName) |
|
280 | { |
||
281 | 29 | $columns = $this->listTableColumns($tableName); |
|
282 | 29 | $foreignKeys = []; |
|
283 | 29 | if ($this->_platform->supportsForeignKeyConstraints()) { |
|
284 | $foreignKeys = $this->listTableForeignKeys($tableName); |
||
285 | } |
||
286 | 29 | $indexes = $this->listTableIndexes($tableName); |
|
287 | |||
288 | 29 | return new Table($tableName, $columns, $indexes, $foreignKeys, false, []); |
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Lists the views this connection has. |
||
293 | * |
||
294 | * @return \Doctrine\DBAL\Schema\View[] |
||
295 | */ |
||
296 | 1 | public function listViews() |
|
297 | { |
||
298 | 1 | $database = $this->_conn->getDatabase(); |
|
299 | 1 | $sql = $this->_platform->getListViewsSQL($database); |
|
300 | 1 | $views = $this->_conn->fetchAll($sql); |
|
301 | |||
302 | 1 | return $this->_getPortableViewsList($views); |
|
303 | } |
||
304 | |||
305 | /** |
||
306 | * Lists the foreign keys for the given table. |
||
307 | * |
||
308 | * @param string $table The name of the table. |
||
309 | * @param string|null $database |
||
310 | * |
||
311 | * @return \Doctrine\DBAL\Schema\ForeignKeyConstraint[] |
||
312 | */ |
||
313 | 1 | View Code Duplication | public function listTableForeignKeys($table, $database = null) |
314 | { |
||
315 | 1 | if (is_null($database)) { |
|
316 | 1 | $database = $this->_conn->getDatabase(); |
|
317 | } |
||
318 | 1 | $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); |
|
319 | 1 | $tableForeignKeys = $this->_conn->fetchAll($sql); |
|
320 | |||
321 | 1 | return $this->_getPortableTableForeignKeysList($tableForeignKeys); |
|
322 | } |
||
323 | |||
324 | /* drop*() Methods */ |
||
325 | |||
326 | /** |
||
327 | * Drops a database. |
||
328 | * |
||
329 | * NOTE: You can not drop the database this SchemaManager is currently connected to. |
||
330 | * |
||
331 | * @param string $database The name of the database to drop. |
||
332 | * |
||
333 | * @return void |
||
334 | */ |
||
335 | public function dropDatabase($database) |
||
336 | { |
||
337 | $this->_execSql($this->_platform->getDropDatabaseSQL($database)); |
||
338 | } |
||
339 | |||
340 | /** |
||
341 | * Drops the given table. |
||
342 | * |
||
343 | * @param string $tableName The name of the table to drop. |
||
344 | * |
||
345 | * @return void |
||
346 | */ |
||
347 | 61 | public function dropTable($tableName) |
|
348 | { |
||
349 | 61 | $this->_execSql($this->_platform->getDropTableSQL($tableName)); |
|
350 | 46 | } |
|
351 | |||
352 | /** |
||
353 | * Drops the index from the given table. |
||
354 | * |
||
355 | * @param \Doctrine\DBAL\Schema\Index|string $index The name of the index. |
||
356 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table. |
||
357 | * |
||
358 | * @return void |
||
359 | */ |
||
360 | 1 | public function dropIndex($index, $table) |
|
361 | { |
||
362 | 1 | if ($index instanceof Index) { |
|
363 | $index = $index->getQuotedName($this->_platform); |
||
364 | } |
||
365 | |||
366 | 1 | $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); |
|
367 | 1 | } |
|
368 | |||
369 | /** |
||
370 | * Drops the constraint from the given table. |
||
371 | * |
||
372 | * @param \Doctrine\DBAL\Schema\Constraint $constraint |
||
373 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table. |
||
374 | * |
||
375 | * @return void |
||
376 | */ |
||
377 | public function dropConstraint(Constraint $constraint, $table) |
||
378 | { |
||
379 | $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * Drops a foreign key from a table. |
||
384 | * |
||
385 | * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint|string $foreignKey The name of the foreign key. |
||
386 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table with the foreign key. |
||
387 | * |
||
388 | * @return void |
||
389 | */ |
||
390 | public function dropForeignKey($foreignKey, $table) |
||
391 | { |
||
392 | $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table)); |
||
393 | } |
||
394 | |||
395 | /** |
||
396 | * Drops a sequence with a given name. |
||
397 | * |
||
398 | * @param string $name The name of the sequence to drop. |
||
399 | * |
||
400 | * @return void |
||
401 | */ |
||
402 | public function dropSequence($name) |
||
403 | { |
||
404 | $this->_execSql($this->_platform->getDropSequenceSQL($name)); |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * Drops a view. |
||
409 | * |
||
410 | * @param string $name The name of the view. |
||
411 | * |
||
412 | * @return void |
||
413 | */ |
||
414 | 1 | public function dropView($name) |
|
415 | { |
||
416 | 1 | $this->_execSql($this->_platform->getDropViewSQL($name)); |
|
417 | } |
||
418 | |||
419 | /* create*() Methods */ |
||
420 | |||
421 | /** |
||
422 | * Creates a new database. |
||
423 | * |
||
424 | * @param string $database The name of the database to create. |
||
425 | * |
||
426 | * @return void |
||
427 | */ |
||
428 | public function createDatabase($database) |
||
429 | { |
||
430 | $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); |
||
431 | } |
||
432 | |||
433 | /** |
||
434 | * Creates a new table. |
||
435 | * |
||
436 | * @param \Doctrine\DBAL\Schema\Table $table |
||
437 | * |
||
438 | * @return void |
||
439 | */ |
||
440 | 117 | public function createTable(Table $table) |
|
441 | { |
||
442 | 117 | $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; |
|
443 | 117 | $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); |
|
444 | 85 | } |
|
445 | |||
446 | /** |
||
447 | * Creates a new sequence. |
||
448 | * |
||
449 | * @param \Doctrine\DBAL\Schema\Sequence $sequence |
||
450 | * |
||
451 | * @return void |
||
452 | * |
||
453 | * @throws \Doctrine\DBAL\ConnectionException If something fails at database level. |
||
454 | */ |
||
455 | public function createSequence($sequence) |
||
456 | { |
||
457 | $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); |
||
458 | } |
||
459 | |||
460 | /** |
||
461 | * Creates a constraint on a table. |
||
462 | * |
||
463 | * @param \Doctrine\DBAL\Schema\Constraint $constraint |
||
464 | * @param \Doctrine\DBAL\Schema\Table|string $table |
||
465 | * |
||
466 | * @return void |
||
467 | */ |
||
468 | public function createConstraint(Constraint $constraint, $table) |
||
469 | { |
||
470 | $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * Creates a new index on a table. |
||
475 | * |
||
476 | * @param \Doctrine\DBAL\Schema\Index $index |
||
477 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created. |
||
478 | * |
||
479 | * @return void |
||
480 | */ |
||
481 | 1 | public function createIndex(Index $index, $table) |
|
482 | { |
||
483 | 1 | $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); |
|
484 | 1 | } |
|
485 | |||
486 | /** |
||
487 | * Creates a new foreign key. |
||
488 | * |
||
489 | * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey The ForeignKey instance. |
||
490 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created. |
||
491 | * |
||
492 | * @return void |
||
493 | */ |
||
494 | public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) |
||
495 | { |
||
496 | $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); |
||
497 | } |
||
498 | |||
499 | /** |
||
500 | * Creates a new view. |
||
501 | * |
||
502 | * @param \Doctrine\DBAL\Schema\View $view |
||
503 | * |
||
504 | * @return void |
||
505 | */ |
||
506 | 1 | public function createView(View $view) |
|
507 | { |
||
508 | 1 | $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); |
|
509 | 1 | } |
|
510 | |||
511 | /* dropAndCreate*() Methods */ |
||
512 | |||
513 | /** |
||
514 | * Drops and creates a constraint. |
||
515 | * |
||
516 | * @see dropConstraint() |
||
517 | * @see createConstraint() |
||
518 | * |
||
519 | * @param \Doctrine\DBAL\Schema\Constraint $constraint |
||
520 | * @param \Doctrine\DBAL\Schema\Table|string $table |
||
521 | * |
||
522 | * @return void |
||
523 | */ |
||
524 | public function dropAndCreateConstraint(Constraint $constraint, $table) |
||
525 | { |
||
526 | $this->tryMethod('dropConstraint', $constraint, $table); |
||
527 | $this->createConstraint($constraint, $table); |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * Drops and creates a new index on a table. |
||
532 | * |
||
533 | * @param \Doctrine\DBAL\Schema\Index $index |
||
534 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the index is to be created. |
||
535 | * |
||
536 | * @return void |
||
537 | */ |
||
538 | 1 | public function dropAndCreateIndex(Index $index, $table) |
|
539 | { |
||
540 | 1 | $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); |
|
541 | 1 | $this->createIndex($index, $table); |
|
542 | 1 | } |
|
543 | |||
544 | /** |
||
545 | * Drops and creates a new foreign key. |
||
546 | * |
||
547 | * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created. |
||
548 | * @param \Doctrine\DBAL\Schema\Table|string $table The name of the table on which the foreign key is to be created. |
||
549 | * |
||
550 | * @return void |
||
551 | */ |
||
552 | public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) |
||
553 | { |
||
554 | $this->tryMethod('dropForeignKey', $foreignKey, $table); |
||
555 | $this->createForeignKey($foreignKey, $table); |
||
556 | } |
||
557 | |||
558 | /** |
||
559 | * Drops and create a new sequence. |
||
560 | * |
||
561 | * @param \Doctrine\DBAL\Schema\Sequence $sequence |
||
562 | * |
||
563 | * @return void |
||
564 | * |
||
565 | * @throws \Doctrine\DBAL\ConnectionException If something fails at database level. |
||
566 | */ |
||
567 | public function dropAndCreateSequence(Sequence $sequence) |
||
568 | { |
||
569 | $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform)); |
||
570 | $this->createSequence($sequence); |
||
571 | } |
||
572 | |||
573 | /** |
||
574 | * Drops and creates a new table. |
||
575 | * |
||
576 | * @param \Doctrine\DBAL\Schema\Table $table |
||
577 | * |
||
578 | * @return void |
||
579 | */ |
||
580 | 48 | public function dropAndCreateTable(Table $table) |
|
581 | { |
||
582 | 48 | $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); |
|
583 | 48 | $this->createTable($table); |
|
584 | 48 | } |
|
585 | |||
586 | /** |
||
587 | * Drops and creates a new database. |
||
588 | * |
||
589 | * @param string $database The name of the database to create. |
||
590 | * |
||
591 | * @return void |
||
592 | */ |
||
593 | 1 | public function dropAndCreateDatabase($database) |
|
594 | { |
||
595 | 1 | $this->tryMethod('dropDatabase', $database); |
|
596 | 1 | $this->createDatabase($database); |
|
597 | 1 | } |
|
598 | |||
599 | /** |
||
600 | * Drops and creates a new view. |
||
601 | * |
||
602 | * @param \Doctrine\DBAL\Schema\View $view |
||
603 | * |
||
604 | * @return void |
||
605 | */ |
||
606 | 1 | public function dropAndCreateView(View $view) |
|
607 | { |
||
608 | 1 | $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); |
|
609 | 1 | $this->createView($view); |
|
610 | 1 | } |
|
611 | |||
612 | /* alterTable() Methods */ |
||
613 | |||
614 | /** |
||
615 | * Alters an existing tables schema. |
||
616 | * |
||
617 | * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff |
||
618 | * |
||
619 | * @return void |
||
620 | */ |
||
621 | 14 | public function alterTable(TableDiff $tableDiff) |
|
622 | { |
||
623 | 14 | $queries = $this->_platform->getAlterTableSQL($tableDiff); |
|
624 | 14 | if (is_array($queries) && count($queries)) { |
|
625 | 14 | foreach ($queries as $ddlQuery) { |
|
626 | 14 | $this->_execSql($ddlQuery); |
|
627 | } |
||
628 | } |
||
629 | 14 | } |
|
630 | |||
631 | /** |
||
632 | * Renames a given table to another name. |
||
633 | * |
||
634 | * @param string $name The current name of the table. |
||
635 | * @param string $newName The new name of the table. |
||
636 | * |
||
637 | * @return void |
||
638 | */ |
||
639 | public function renameTable($name, $newName) |
||
640 | { |
||
641 | $tableDiff = new TableDiff($name); |
||
642 | $tableDiff->newName = $newName; |
||
643 | $this->alterTable($tableDiff); |
||
644 | } |
||
645 | |||
646 | /** |
||
647 | * Methods for filtering return values of list*() methods to convert |
||
648 | * the native DBMS data definition to a portable Doctrine definition |
||
649 | */ |
||
650 | |||
651 | /** |
||
652 | * @param array $databases |
||
653 | * |
||
654 | * @return array |
||
655 | */ |
||
656 | protected function _getPortableDatabasesList($databases) |
||
657 | { |
||
658 | $list = []; |
||
659 | foreach ($databases as $value) { |
||
660 | if ($value = $this->_getPortableDatabaseDefinition($value)) { |
||
661 | $list[] = $value; |
||
662 | } |
||
663 | } |
||
664 | |||
665 | return $list; |
||
666 | } |
||
667 | |||
668 | /** |
||
669 | * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. |
||
670 | * |
||
671 | * @param array $namespaces The list of namespace names in the native DBMS data definition. |
||
672 | * |
||
673 | * @return array |
||
674 | */ |
||
675 | protected function getPortableNamespacesList(array $namespaces) |
||
676 | { |
||
677 | $namespacesList = []; |
||
678 | |||
679 | foreach ($namespaces as $namespace) { |
||
680 | $namespacesList[] = $this->getPortableNamespaceDefinition($namespace); |
||
681 | } |
||
682 | |||
683 | return $namespacesList; |
||
684 | } |
||
685 | |||
686 | /** |
||
687 | * @param array $database |
||
688 | * |
||
689 | * @return mixed |
||
690 | */ |
||
691 | protected function _getPortableDatabaseDefinition($database) |
||
692 | { |
||
693 | return $database; |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. |
||
698 | * |
||
699 | * @param array $namespace The native DBMS namespace definition. |
||
700 | * |
||
701 | * @return mixed |
||
702 | */ |
||
703 | protected function getPortableNamespaceDefinition(array $namespace) |
||
704 | { |
||
705 | return $namespace; |
||
706 | } |
||
707 | |||
708 | /** |
||
709 | * @param array $functions |
||
710 | * |
||
711 | * @return array |
||
712 | */ |
||
713 | protected function _getPortableFunctionsList($functions) |
||
714 | { |
||
715 | $list = []; |
||
716 | foreach ($functions as $value) { |
||
717 | if ($value = $this->_getPortableFunctionDefinition($value)) { |
||
718 | $list[] = $value; |
||
719 | } |
||
720 | } |
||
721 | |||
722 | return $list; |
||
723 | } |
||
724 | |||
725 | /** |
||
726 | * @param array $function |
||
727 | * |
||
728 | * @return mixed |
||
729 | */ |
||
730 | protected function _getPortableFunctionDefinition($function) |
||
731 | { |
||
732 | return $function; |
||
733 | } |
||
734 | |||
735 | /** |
||
736 | * @param array $triggers |
||
737 | * |
||
738 | * @return array |
||
739 | */ |
||
740 | protected function _getPortableTriggersList($triggers) |
||
741 | { |
||
742 | $list = []; |
||
743 | foreach ($triggers as $value) { |
||
744 | if ($value = $this->_getPortableTriggerDefinition($value)) { |
||
745 | $list[] = $value; |
||
746 | } |
||
747 | } |
||
748 | |||
749 | return $list; |
||
750 | } |
||
751 | |||
752 | /** |
||
753 | * @param array $trigger |
||
754 | * |
||
755 | * @return mixed |
||
756 | */ |
||
757 | protected function _getPortableTriggerDefinition($trigger) |
||
758 | { |
||
759 | return $trigger; |
||
760 | } |
||
761 | |||
762 | /** |
||
763 | * @param array $sequences |
||
764 | * |
||
765 | * @return array |
||
766 | */ |
||
767 | protected function _getPortableSequencesList($sequences) |
||
768 | { |
||
769 | $list = []; |
||
770 | foreach ($sequences as $value) { |
||
771 | if ($value = $this->_getPortableSequenceDefinition($value)) { |
||
772 | $list[] = $value; |
||
773 | } |
||
774 | } |
||
775 | |||
776 | return $list; |
||
777 | } |
||
778 | |||
779 | /** |
||
780 | * @param array $sequence |
||
781 | * |
||
782 | * @return \Doctrine\DBAL\Schema\Sequence |
||
783 | * |
||
784 | * @throws \Doctrine\DBAL\DBALException |
||
785 | */ |
||
786 | protected function _getPortableSequenceDefinition($sequence) |
||
787 | { |
||
788 | throw DBALException::notSupported('Sequences'); |
||
789 | } |
||
790 | |||
791 | /** |
||
792 | * Independent of the database the keys of the column list result are lowercased. |
||
793 | * |
||
794 | * The name of the created column instance however is kept in its case. |
||
795 | * |
||
796 | * @param string $table The name of the table. |
||
797 | * @param string $database |
||
798 | * @param array $tableColumns |
||
799 | * |
||
800 | * @return array |
||
801 | */ |
||
802 | 40 | protected function _getPortableTableColumnList($table, $database, $tableColumns) |
|
803 | { |
||
804 | 40 | $eventManager = $this->_platform->getEventManager(); |
|
805 | |||
806 | 40 | $list = []; |
|
807 | 40 | foreach ($tableColumns as $tableColumn) { |
|
808 | 40 | $column = null; |
|
809 | 40 | $defaultPrevented = false; |
|
810 | |||
811 | 40 | View Code Duplication | if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) { |
812 | 1 | $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn); |
|
813 | 1 | $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs); |
|
814 | |||
815 | 1 | $defaultPrevented = $eventArgs->isDefaultPrevented(); |
|
816 | 1 | $column = $eventArgs->getColumn(); |
|
817 | } |
||
818 | |||
819 | 40 | if ( ! $defaultPrevented) { |
|
820 | 40 | $column = $this->_getPortableTableColumnDefinition($tableColumn); |
|
821 | } |
||
822 | |||
823 | 40 | if ($column) { |
|
824 | 40 | $name = strtolower($column->getQuotedName($this->_platform)); |
|
825 | 40 | $list[$name] = $column; |
|
826 | } |
||
827 | } |
||
828 | |||
829 | 40 | return $list; |
|
830 | } |
||
831 | |||
832 | /** |
||
833 | * Gets Table Column Definition. |
||
834 | * |
||
835 | * @param array $tableColumn |
||
836 | * |
||
837 | * @return \Doctrine\DBAL\Schema\Column |
||
838 | */ |
||
839 | abstract protected function _getPortableTableColumnDefinition($tableColumn); |
||
840 | |||
841 | /** |
||
842 | * Aggregates and groups the index results according to the required data result. |
||
843 | * |
||
844 | * @param array $tableIndexRows |
||
845 | * @param string|null $tableName |
||
846 | * |
||
847 | * @return array |
||
848 | */ |
||
849 | 33 | protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) |
|
850 | { |
||
851 | 33 | $result = []; |
|
852 | 33 | foreach ($tableIndexRows as $tableIndex) { |
|
853 | 21 | $indexName = $keyName = $tableIndex['key_name']; |
|
854 | 21 | if ($tableIndex['primary']) { |
|
855 | 21 | $keyName = 'primary'; |
|
856 | } |
||
857 | 21 | $keyName = strtolower($keyName); |
|
858 | |||
859 | 21 | if (!isset($result[$keyName])) { |
|
860 | 21 | $result[$keyName] = [ |
|
861 | 21 | 'name' => $indexName, |
|
862 | 21 | 'columns' => [$tableIndex['column_name']], |
|
863 | 21 | 'unique' => $tableIndex['non_unique'] ? false : true, |
|
864 | 21 | 'primary' => $tableIndex['primary'], |
|
865 | 21 | 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : [], |
|
866 | 21 | 'options' => isset($tableIndex['where']) ? ['where' => $tableIndex['where']] : [], |
|
867 | ]; |
||
868 | } else { |
||
869 | 21 | $result[$keyName]['columns'][] = $tableIndex['column_name']; |
|
870 | } |
||
871 | } |
||
872 | |||
873 | 33 | $eventManager = $this->_platform->getEventManager(); |
|
874 | |||
875 | 33 | $indexes = []; |
|
876 | 33 | foreach ($result as $indexKey => $data) { |
|
877 | 21 | $index = null; |
|
878 | 21 | $defaultPrevented = false; |
|
879 | |||
880 | 21 | View Code Duplication | if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { |
881 | 1 | $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); |
|
882 | 1 | $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); |
|
883 | |||
884 | 1 | $defaultPrevented = $eventArgs->isDefaultPrevented(); |
|
885 | 1 | $index = $eventArgs->getIndex(); |
|
886 | } |
||
887 | |||
888 | 21 | if ( ! $defaultPrevented) { |
|
889 | 21 | $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']); |
|
890 | } |
||
891 | |||
892 | 21 | if ($index) { |
|
893 | 21 | $indexes[$indexKey] = $index; |
|
894 | } |
||
895 | } |
||
896 | |||
897 | 33 | return $indexes; |
|
898 | } |
||
899 | |||
900 | /** |
||
901 | * @param array $tables |
||
902 | * |
||
903 | * @return array |
||
904 | */ |
||
905 | 58 | protected function _getPortableTablesList($tables) |
|
906 | { |
||
907 | 58 | $list = []; |
|
908 | 58 | foreach ($tables as $value) { |
|
909 | 57 | if ($value = $this->_getPortableTableDefinition($value)) { |
|
910 | 57 | $list[] = $value; |
|
911 | } |
||
912 | } |
||
913 | |||
914 | 58 | return $list; |
|
915 | } |
||
916 | |||
917 | /** |
||
918 | * @param array $table |
||
919 | * |
||
920 | * @return array |
||
921 | */ |
||
922 | protected function _getPortableTableDefinition($table) |
||
923 | { |
||
924 | return $table; |
||
925 | } |
||
926 | |||
927 | /** |
||
928 | * @param array $users |
||
929 | * |
||
930 | * @return array |
||
931 | */ |
||
932 | protected function _getPortableUsersList($users) |
||
933 | { |
||
934 | $list = []; |
||
935 | foreach ($users as $value) { |
||
936 | if ($value = $this->_getPortableUserDefinition($value)) { |
||
937 | $list[] = $value; |
||
938 | } |
||
939 | } |
||
940 | |||
941 | return $list; |
||
942 | } |
||
943 | |||
944 | /** |
||
945 | * @param array $user |
||
946 | * |
||
947 | * @return mixed |
||
948 | */ |
||
949 | protected function _getPortableUserDefinition($user) |
||
950 | { |
||
951 | return $user; |
||
952 | } |
||
953 | |||
954 | /** |
||
955 | * @param array $views |
||
956 | * |
||
957 | * @return array |
||
958 | */ |
||
959 | 1 | protected function _getPortableViewsList($views) |
|
960 | { |
||
961 | 1 | $list = []; |
|
962 | 1 | foreach ($views as $value) { |
|
963 | 1 | if ($view = $this->_getPortableViewDefinition($value)) { |
|
964 | 1 | $viewName = strtolower($view->getQuotedName($this->_platform)); |
|
965 | 1 | $list[$viewName] = $view; |
|
966 | } |
||
967 | } |
||
968 | |||
969 | 1 | return $list; |
|
970 | } |
||
971 | |||
972 | /** |
||
973 | * @param array $view |
||
974 | * |
||
975 | * @return mixed |
||
976 | */ |
||
977 | protected function _getPortableViewDefinition($view) |
||
978 | { |
||
979 | return false; |
||
980 | } |
||
981 | |||
982 | /** |
||
983 | * @param array $tableForeignKeys |
||
984 | * |
||
985 | * @return array |
||
986 | */ |
||
987 | protected function _getPortableTableForeignKeysList($tableForeignKeys) |
||
988 | { |
||
989 | $list = []; |
||
990 | foreach ($tableForeignKeys as $value) { |
||
991 | if ($value = $this->_getPortableTableForeignKeyDefinition($value)) { |
||
992 | $list[] = $value; |
||
993 | } |
||
994 | } |
||
995 | |||
996 | return $list; |
||
997 | } |
||
998 | |||
999 | /** |
||
1000 | * @param array $tableForeignKey |
||
1001 | * |
||
1002 | * @return mixed |
||
1003 | */ |
||
1004 | protected function _getPortableTableForeignKeyDefinition($tableForeignKey) |
||
1005 | { |
||
1006 | return $tableForeignKey; |
||
1007 | } |
||
1008 | |||
1009 | /** |
||
1010 | * @param array|string $sql |
||
1011 | * |
||
1012 | * @return void |
||
1013 | */ |
||
1014 | 117 | protected function _execSql($sql) |
|
1015 | { |
||
1016 | 117 | foreach ((array) $sql as $query) { |
|
1017 | 117 | $this->_conn->executeUpdate($query); |
|
1018 | } |
||
1019 | 85 | } |
|
1020 | |||
1021 | /** |
||
1022 | * Creates a schema instance for the current database. |
||
1023 | * |
||
1024 | * @return \Doctrine\DBAL\Schema\Schema |
||
1025 | */ |
||
1026 | 4 | public function createSchema() |
|
1027 | { |
||
1028 | 4 | $namespaces = []; |
|
1029 | |||
1030 | 4 | if ($this->_platform->supportsSchemas()) { |
|
1031 | $namespaces = $this->listNamespaceNames(); |
||
1032 | } |
||
1033 | |||
1034 | 4 | $sequences = []; |
|
1035 | |||
1036 | 4 | if ($this->_platform->supportsSequences()) { |
|
1037 | $sequences = $this->listSequences(); |
||
1038 | } |
||
1039 | |||
1040 | 4 | $tables = $this->listTables(); |
|
1041 | |||
1042 | 4 | return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces); |
|
1043 | } |
||
1044 | |||
1045 | /** |
||
1046 | * Creates the configuration for this schema. |
||
1047 | * |
||
1048 | * @return \Doctrine\DBAL\Schema\SchemaConfig |
||
1049 | */ |
||
1050 | 13 | public function createSchemaConfig() |
|
1051 | { |
||
1052 | 13 | $schemaConfig = new SchemaConfig(); |
|
1053 | 13 | $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); |
|
1054 | |||
1055 | 13 | $searchPaths = $this->getSchemaSearchPaths(); |
|
1056 | 13 | if (isset($searchPaths[0])) { |
|
1057 | $schemaConfig->setName($searchPaths[0]); |
||
1058 | } |
||
1059 | |||
1060 | 13 | $params = $this->_conn->getParams(); |
|
1061 | 13 | if (isset($params['defaultTableOptions'])) { |
|
1062 | $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']); |
||
1063 | } |
||
1064 | |||
1065 | 13 | return $schemaConfig; |
|
1066 | } |
||
1067 | |||
1068 | /** |
||
1069 | * The search path for namespaces in the currently connected database. |
||
1070 | * |
||
1071 | * The first entry is usually the default namespace in the Schema. All |
||
1072 | * further namespaces contain tables/sequences which can also be addressed |
||
1073 | * with a short, not full-qualified name. |
||
1074 | * |
||
1075 | * For databases that don't support subschema/namespaces this method |
||
1076 | * returns the name of the currently connected database. |
||
1077 | * |
||
1078 | * @return array |
||
1079 | */ |
||
1080 | 13 | public function getSchemaSearchPaths() |
|
1081 | { |
||
1082 | 13 | return [$this->_conn->getDatabase()]; |
|
1083 | } |
||
1084 | |||
1085 | /** |
||
1086 | * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns |
||
1087 | * the type given as default. |
||
1088 | * |
||
1089 | * @param string $comment |
||
1090 | * @param string $currentType |
||
1091 | * |
||
1092 | * @return string |
||
1093 | */ |
||
1094 | 17 | public function extractDoctrineTypeFromComment($comment, $currentType) |
|
1095 | { |
||
1096 | 17 | if (preg_match("(\(DC2Type:([a-zA-Z0-9_]+)\))", $comment, $match)) { |
|
1097 | 4 | $currentType = $match[1]; |
|
1098 | } |
||
1099 | |||
1100 | 17 | return $currentType; |
|
1101 | } |
||
1102 | |||
1103 | /** |
||
1104 | * @param string $comment |
||
1105 | * @param string $type |
||
1106 | * |
||
1107 | * @return string |
||
1108 | */ |
||
1109 | 5 | public function removeDoctrineTypeFromComment($comment, $type) |
|
1110 | { |
||
1111 | 5 | return str_replace('(DC2Type:'.$type.')', '', $comment); |
|
1112 | } |
||
1113 | } |
||
1114 |