AbstractSchemaManager.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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 LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\DBAL\Schema;
  20. use Doctrine\DBAL\Events;
  21. use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
  22. use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
  23. use Doctrine\DBAL\Types;
  24. use Doctrine\DBAL\DBALException;
  25. use Doctrine\DBAL\Platforms\AbstractPlatform;
  26. /**
  27. * Base class for schema managers. Schema managers are used to inspect and/or
  28. * modify the database schema/structure.
  29. *
  30. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  31. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
  32. * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  33. * @author Roman Borschel <roman@code-factory.org>
  34. * @author Jonathan H. Wage <jonwage@gmail.com>
  35. * @author Benjamin Eberlei <kontakt@beberlei.de>
  36. * @since 2.0
  37. */
  38. abstract class AbstractSchemaManager
  39. {
  40. /**
  41. * Holds instance of the Doctrine connection for this schema manager
  42. *
  43. * @var \Doctrine\DBAL\Connection
  44. */
  45. protected $_conn;
  46. /**
  47. * Holds instance of the database platform used for this schema manager
  48. *
  49. * @var \Doctrine\DBAL\Platforms\AbstractPlatform
  50. */
  51. protected $_platform;
  52. /**
  53. * Constructor. Accepts the Connection instance to manage the schema for
  54. *
  55. * @param \Doctrine\DBAL\Connection $conn
  56. */
  57. public function __construct(\Doctrine\DBAL\Connection $conn)
  58. {
  59. $this->_conn = $conn;
  60. $this->_platform = $this->_conn->getDatabasePlatform();
  61. }
  62. /**
  63. * Return associated platform.
  64. *
  65. * @return \Doctrine\DBAL\Platform\AbstractPlatform
  66. */
  67. public function getDatabasePlatform()
  68. {
  69. return $this->_platform;
  70. }
  71. /**
  72. * Try any method on the schema manager. Normally a method throws an
  73. * exception when your DBMS doesn't support it or if an error occurs.
  74. * This method allows you to try and method on your SchemaManager
  75. * instance and will return false if it does not work or is not supported.
  76. *
  77. * <code>
  78. * $result = $sm->tryMethod('dropView', 'view_name');
  79. * </code>
  80. *
  81. * @return mixed
  82. */
  83. public function tryMethod()
  84. {
  85. $args = func_get_args();
  86. $method = $args[0];
  87. unset($args[0]);
  88. $args = array_values($args);
  89. try {
  90. return call_user_func_array(array($this, $method), $args);
  91. } catch (\Exception $e) {
  92. return false;
  93. }
  94. }
  95. /**
  96. * List the available databases for this connection
  97. *
  98. * @return array $databases
  99. */
  100. public function listDatabases()
  101. {
  102. $sql = $this->_platform->getListDatabasesSQL();
  103. $databases = $this->_conn->fetchAll($sql);
  104. return $this->_getPortableDatabasesList($databases);
  105. }
  106. /**
  107. * List the available sequences for this connection
  108. *
  109. * @return Sequence[]
  110. */
  111. public function listSequences($database = null)
  112. {
  113. if (is_null($database)) {
  114. $database = $this->_conn->getDatabase();
  115. }
  116. $sql = $this->_platform->getListSequencesSQL($database);
  117. $sequences = $this->_conn->fetchAll($sql);
  118. return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
  119. }
  120. /**
  121. * List the columns for a given table.
  122. *
  123. * In contrast to other libraries and to the old version of Doctrine,
  124. * this column definition does try to contain the 'primary' field for
  125. * the reason that it is not portable accross different RDBMS. Use
  126. * {@see listTableIndexes($tableName)} to retrieve the primary key
  127. * of a table. We're a RDBMS specifies more details these are held
  128. * in the platformDetails array.
  129. *
  130. * @param string $table The name of the table.
  131. * @param string $database
  132. * @return Column[]
  133. */
  134. public function listTableColumns($table, $database = null)
  135. {
  136. if (!$database) {
  137. $database = $this->_conn->getDatabase();
  138. }
  139. $sql = $this->_platform->getListTableColumnsSQL($table, $database);
  140. $tableColumns = $this->_conn->fetchAll($sql);
  141. return $this->_getPortableTableColumnList($table, $database, $tableColumns);
  142. }
  143. /**
  144. * List the indexes for a given table returning an array of Index instances.
  145. *
  146. * Keys of the portable indexes list are all lower-cased.
  147. *
  148. * @param string $table The name of the table
  149. * @return Index[] $tableIndexes
  150. */
  151. public function listTableIndexes($table)
  152. {
  153. $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
  154. $tableIndexes = $this->_conn->fetchAll($sql);
  155. return $this->_getPortableTableIndexesList($tableIndexes, $table);
  156. }
  157. /**
  158. * Return true if all the given tables exist.
  159. *
  160. * @param array $tableNames
  161. * @return bool
  162. */
  163. public function tablesExist($tableNames)
  164. {
  165. $tableNames = array_map('strtolower', (array)$tableNames);
  166. return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
  167. }
  168. /**
  169. * Return a list of all tables in the current database
  170. *
  171. * @return array
  172. */
  173. public function listTableNames()
  174. {
  175. $sql = $this->_platform->getListTablesSQL();
  176. $tables = $this->_conn->fetchAll($sql);
  177. $tableNames = $this->_getPortableTablesList($tables);
  178. return $this->filterAssetNames($tableNames);
  179. }
  180. /**
  181. * Filter asset names if they are configured to return only a subset of all
  182. * the found elements.
  183. *
  184. * @param array $assetNames
  185. * @return array
  186. */
  187. protected function filterAssetNames($assetNames)
  188. {
  189. $filterExpr = $this->getFilterSchemaAssetsExpression();
  190. if (!$filterExpr) {
  191. return $assetNames;
  192. }
  193. return array_values (
  194. array_filter($assetNames, function ($assetName) use ($filterExpr) {
  195. $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName;
  196. return preg_match('(' . $filterExpr . ')', $assetName);
  197. })
  198. );
  199. }
  200. protected function getFilterSchemaAssetsExpression()
  201. {
  202. return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();
  203. }
  204. /**
  205. * List the tables for this connection
  206. *
  207. * @return Table[]
  208. */
  209. public function listTables()
  210. {
  211. $tableNames = $this->listTableNames();
  212. $tables = array();
  213. foreach ($tableNames AS $tableName) {
  214. $tables[] = $this->listTableDetails($tableName);
  215. }
  216. return $tables;
  217. }
  218. /**
  219. * @param string $tableName
  220. * @return Table
  221. */
  222. public function listTableDetails($tableName)
  223. {
  224. $columns = $this->listTableColumns($tableName);
  225. $foreignKeys = array();
  226. if ($this->_platform->supportsForeignKeyConstraints()) {
  227. $foreignKeys = $this->listTableForeignKeys($tableName);
  228. }
  229. $indexes = $this->listTableIndexes($tableName);
  230. return new Table($tableName, $columns, $indexes, $foreignKeys, false, array());
  231. }
  232. /**
  233. * List the views this connection has
  234. *
  235. * @return View[]
  236. */
  237. public function listViews()
  238. {
  239. $database = $this->_conn->getDatabase();
  240. $sql = $this->_platform->getListViewsSQL($database);
  241. $views = $this->_conn->fetchAll($sql);
  242. return $this->_getPortableViewsList($views);
  243. }
  244. /**
  245. * List the foreign keys for the given table
  246. *
  247. * @param string $table The name of the table
  248. * @return ForeignKeyConstraint[]
  249. */
  250. public function listTableForeignKeys($table, $database = null)
  251. {
  252. if (is_null($database)) {
  253. $database = $this->_conn->getDatabase();
  254. }
  255. $sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
  256. $tableForeignKeys = $this->_conn->fetchAll($sql);
  257. return $this->_getPortableTableForeignKeysList($tableForeignKeys);
  258. }
  259. /* drop*() Methods */
  260. /**
  261. * Drops a database.
  262. *
  263. * NOTE: You can not drop the database this SchemaManager is currently connected to.
  264. *
  265. * @param string $database The name of the database to drop
  266. */
  267. public function dropDatabase($database)
  268. {
  269. $this->_execSql($this->_platform->getDropDatabaseSQL($database));
  270. }
  271. /**
  272. * Drop the given table
  273. *
  274. * @param string $table The name of the table to drop
  275. */
  276. public function dropTable($table)
  277. {
  278. $this->_execSql($this->_platform->getDropTableSQL($table));
  279. }
  280. /**
  281. * Drop the index from the given table
  282. *
  283. * @param Index|string $index The name of the index
  284. * @param string|Table $table The name of the table
  285. */
  286. public function dropIndex($index, $table)
  287. {
  288. if($index instanceof Index) {
  289. $index = $index->getQuotedName($this->_platform);
  290. }
  291. $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
  292. }
  293. /**
  294. * Drop the constraint from the given table
  295. *
  296. * @param Constraint $constraint
  297. * @param string $table The name of the table
  298. */
  299. public function dropConstraint(Constraint $constraint, $table)
  300. {
  301. $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
  302. }
  303. /**
  304. * Drops a foreign key from a table.
  305. *
  306. * @param ForeignKeyConstraint|string $table The name of the table with the foreign key.
  307. * @param Table|string $name The name of the foreign key.
  308. * @return boolean $result
  309. */
  310. public function dropForeignKey($foreignKey, $table)
  311. {
  312. $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
  313. }
  314. /**
  315. * Drops a sequence with a given name.
  316. *
  317. * @param string $name The name of the sequence to drop.
  318. */
  319. public function dropSequence($name)
  320. {
  321. $this->_execSql($this->_platform->getDropSequenceSQL($name));
  322. }
  323. /**
  324. * Drop a view
  325. *
  326. * @param string $name The name of the view
  327. * @return boolean $result
  328. */
  329. public function dropView($name)
  330. {
  331. $this->_execSql($this->_platform->getDropViewSQL($name));
  332. }
  333. /* create*() Methods */
  334. /**
  335. * Creates a new database.
  336. *
  337. * @param string $database The name of the database to create.
  338. */
  339. public function createDatabase($database)
  340. {
  341. $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
  342. }
  343. /**
  344. * Create a new table.
  345. *
  346. * @param Table $table
  347. * @param int $createFlags
  348. */
  349. public function createTable(Table $table)
  350. {
  351. $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
  352. $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
  353. }
  354. /**
  355. * Create a new sequence
  356. *
  357. * @param Sequence $sequence
  358. * @throws Doctrine\DBAL\ConnectionException if something fails at database level
  359. */
  360. public function createSequence($sequence)
  361. {
  362. $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
  363. }
  364. /**
  365. * Create a constraint on a table
  366. *
  367. * @param Constraint $constraint
  368. * @param string|Table $table
  369. */
  370. public function createConstraint(Constraint $constraint, $table)
  371. {
  372. $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
  373. }
  374. /**
  375. * Create a new index on a table
  376. *
  377. * @param Index $index
  378. * @param string $table name of the table on which the index is to be created
  379. */
  380. public function createIndex(Index $index, $table)
  381. {
  382. $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
  383. }
  384. /**
  385. * Create a new foreign key
  386. *
  387. * @param ForeignKeyConstraint $foreignKey ForeignKey instance
  388. * @param string|Table $table name of the table on which the foreign key is to be created
  389. */
  390. public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
  391. {
  392. $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
  393. }
  394. /**
  395. * Create a new view
  396. *
  397. * @param View $view
  398. */
  399. public function createView(View $view)
  400. {
  401. $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
  402. }
  403. /* dropAndCreate*() Methods */
  404. /**
  405. * Drop and create a constraint
  406. *
  407. * @param Constraint $constraint
  408. * @param string $table
  409. * @see dropConstraint()
  410. * @see createConstraint()
  411. */
  412. public function dropAndCreateConstraint(Constraint $constraint, $table)
  413. {
  414. $this->tryMethod('dropConstraint', $constraint, $table);
  415. $this->createConstraint($constraint, $table);
  416. }
  417. /**
  418. * Drop and create a new index on a table
  419. *
  420. * @param string|Table $table name of the table on which the index is to be created
  421. * @param Index $index
  422. */
  423. public function dropAndCreateIndex(Index $index, $table)
  424. {
  425. $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
  426. $this->createIndex($index, $table);
  427. }
  428. /**
  429. * Drop and create a new foreign key
  430. *
  431. * @param ForeignKeyConstraint $foreignKey associative array that defines properties of the foreign key to be created.
  432. * @param string|Table $table name of the table on which the foreign key is to be created
  433. */
  434. public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
  435. {
  436. $this->tryMethod('dropForeignKey', $foreignKey, $table);
  437. $this->createForeignKey($foreignKey, $table);
  438. }
  439. /**
  440. * Drop and create a new sequence
  441. *
  442. * @param Sequence $sequence
  443. * @throws Doctrine\DBAL\ConnectionException if something fails at database level
  444. */
  445. public function dropAndCreateSequence(Sequence $sequence)
  446. {
  447. $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
  448. $this->createSequence($sequence);
  449. }
  450. /**
  451. * Drop and create a new table.
  452. *
  453. * @param Table $table
  454. */
  455. public function dropAndCreateTable(Table $table)
  456. {
  457. $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
  458. $this->createTable($table);
  459. }
  460. /**
  461. * Drop and creates a new database.
  462. *
  463. * @param string $database The name of the database to create.
  464. */
  465. public function dropAndCreateDatabase($database)
  466. {
  467. $this->tryMethod('dropDatabase', $database);
  468. $this->createDatabase($database);
  469. }
  470. /**
  471. * Drop and create a new view
  472. *
  473. * @param View $view
  474. */
  475. public function dropAndCreateView(View $view)
  476. {
  477. $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
  478. $this->createView($view);
  479. }
  480. /* alterTable() Methods */
  481. /**
  482. * Alter an existing tables schema
  483. *
  484. * @param TableDiff $tableDiff
  485. */
  486. public function alterTable(TableDiff $tableDiff)
  487. {
  488. $queries = $this->_platform->getAlterTableSQL($tableDiff);
  489. if (is_array($queries) && count($queries)) {
  490. foreach ($queries AS $ddlQuery) {
  491. $this->_execSql($ddlQuery);
  492. }
  493. }
  494. }
  495. /**
  496. * Rename a given table to another name
  497. *
  498. * @param string $name The current name of the table
  499. * @param string $newName The new name of the table
  500. */
  501. public function renameTable($name, $newName)
  502. {
  503. $tableDiff = new TableDiff($name);
  504. $tableDiff->newName = $newName;
  505. $this->alterTable($tableDiff);
  506. }
  507. /**
  508. * Methods for filtering return values of list*() methods to convert
  509. * the native DBMS data definition to a portable Doctrine definition
  510. */
  511. protected function _getPortableDatabasesList($databases)
  512. {
  513. $list = array();
  514. foreach ($databases as $key => $value) {
  515. if ($value = $this->_getPortableDatabaseDefinition($value)) {
  516. $list[] = $value;
  517. }
  518. }
  519. return $list;
  520. }
  521. protected function _getPortableDatabaseDefinition($database)
  522. {
  523. return $database;
  524. }
  525. protected function _getPortableFunctionsList($functions)
  526. {
  527. $list = array();
  528. foreach ($functions as $key => $value) {
  529. if ($value = $this->_getPortableFunctionDefinition($value)) {
  530. $list[] = $value;
  531. }
  532. }
  533. return $list;
  534. }
  535. protected function _getPortableFunctionDefinition($function)
  536. {
  537. return $function;
  538. }
  539. protected function _getPortableTriggersList($triggers)
  540. {
  541. $list = array();
  542. foreach ($triggers as $key => $value) {
  543. if ($value = $this->_getPortableTriggerDefinition($value)) {
  544. $list[] = $value;
  545. }
  546. }
  547. return $list;
  548. }
  549. protected function _getPortableTriggerDefinition($trigger)
  550. {
  551. return $trigger;
  552. }
  553. protected function _getPortableSequencesList($sequences)
  554. {
  555. $list = array();
  556. foreach ($sequences as $key => $value) {
  557. if ($value = $this->_getPortableSequenceDefinition($value)) {
  558. $list[] = $value;
  559. }
  560. }
  561. return $list;
  562. }
  563. /**
  564. * @param array $sequence
  565. * @return Sequence
  566. */
  567. protected function _getPortableSequenceDefinition($sequence)
  568. {
  569. throw DBALException::notSupported('Sequences');
  570. }
  571. /**
  572. * Independent of the database the keys of the column list result are lowercased.
  573. *
  574. * The name of the created column instance however is kept in its case.
  575. *
  576. * @param string $table The name of the table.
  577. * @param string $database
  578. * @param array $tableColumns
  579. * @return array
  580. */
  581. protected function _getPortableTableColumnList($table, $database, $tableColumns)
  582. {
  583. $eventManager = $this->_platform->getEventManager();
  584. $list = array();
  585. foreach ($tableColumns as $key => $tableColumn) {
  586. $column = null;
  587. $defaultPrevented = false;
  588. if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
  589. $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
  590. $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
  591. $defaultPrevented = $eventArgs->isDefaultPrevented();
  592. $column = $eventArgs->getColumn();
  593. }
  594. if (!$defaultPrevented) {
  595. $column = $this->_getPortableTableColumnDefinition($tableColumn);
  596. }
  597. if ($column) {
  598. $name = strtolower($column->getQuotedName($this->_platform));
  599. $list[$name] = $column;
  600. }
  601. }
  602. return $list;
  603. }
  604. /**
  605. * Get Table Column Definition
  606. *
  607. * @param array $tableColumn
  608. * @return Column
  609. */
  610. abstract protected function _getPortableTableColumnDefinition($tableColumn);
  611. /**
  612. * Aggregate and group the index results according to the required data result.
  613. *
  614. * @param array $tableIndexRows
  615. * @param string $tableName
  616. * @return array
  617. */
  618. protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
  619. {
  620. $result = array();
  621. foreach($tableIndexRows AS $tableIndex) {
  622. $indexName = $keyName = $tableIndex['key_name'];
  623. if($tableIndex['primary']) {
  624. $keyName = 'primary';
  625. }
  626. $keyName = strtolower($keyName);
  627. if(!isset($result[$keyName])) {
  628. $result[$keyName] = array(
  629. 'name' => $indexName,
  630. 'columns' => array($tableIndex['column_name']),
  631. 'unique' => $tableIndex['non_unique'] ? false : true,
  632. 'primary' => $tableIndex['primary'],
  633. );
  634. } else {
  635. $result[$keyName]['columns'][] = $tableIndex['column_name'];
  636. }
  637. }
  638. $eventManager = $this->_platform->getEventManager();
  639. $indexes = array();
  640. foreach($result AS $indexKey => $data) {
  641. $index = null;
  642. $defaultPrevented = false;
  643. if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
  644. $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
  645. $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
  646. $defaultPrevented = $eventArgs->isDefaultPrevented();
  647. $index = $eventArgs->getIndex();
  648. }
  649. if (!$defaultPrevented) {
  650. $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
  651. }
  652. if ($index) {
  653. $indexes[$indexKey] = $index;
  654. }
  655. }
  656. return $indexes;
  657. }
  658. protected function _getPortableTablesList($tables)
  659. {
  660. $list = array();
  661. foreach ($tables as $key => $value) {
  662. if ($value = $this->_getPortableTableDefinition($value)) {
  663. $list[] = $value;
  664. }
  665. }
  666. return $list;
  667. }
  668. protected function _getPortableTableDefinition($table)
  669. {
  670. return $table;
  671. }
  672. protected function _getPortableUsersList($users)
  673. {
  674. $list = array();
  675. foreach ($users as $key => $value) {
  676. if ($value = $this->_getPortableUserDefinition($value)) {
  677. $list[] = $value;
  678. }
  679. }
  680. return $list;
  681. }
  682. protected function _getPortableUserDefinition($user)
  683. {
  684. return $user;
  685. }
  686. protected function _getPortableViewsList($views)
  687. {
  688. $list = array();
  689. foreach ($views as $key => $value) {
  690. if ($view = $this->_getPortableViewDefinition($value)) {
  691. $viewName = strtolower($view->getQuotedName($this->_platform));
  692. $list[$viewName] = $view;
  693. }
  694. }
  695. return $list;
  696. }
  697. protected function _getPortableViewDefinition($view)
  698. {
  699. return false;
  700. }
  701. protected function _getPortableTableForeignKeysList($tableForeignKeys)
  702. {
  703. $list = array();
  704. foreach ($tableForeignKeys as $key => $value) {
  705. if ($value = $this->_getPortableTableForeignKeyDefinition($value)) {
  706. $list[] = $value;
  707. }
  708. }
  709. return $list;
  710. }
  711. protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
  712. {
  713. return $tableForeignKey;
  714. }
  715. protected function _execSql($sql)
  716. {
  717. foreach ((array) $sql as $query) {
  718. $this->_conn->executeUpdate($query);
  719. }
  720. }
  721. /**
  722. * Create a schema instance for the current database.
  723. *
  724. * @return Schema
  725. */
  726. public function createSchema()
  727. {
  728. $sequences = array();
  729. if($this->_platform->supportsSequences()) {
  730. $sequences = $this->listSequences();
  731. }
  732. $tables = $this->listTables();
  733. return new Schema($tables, $sequences, $this->createSchemaConfig());
  734. }
  735. /**
  736. * Create the configuration for this schema.
  737. *
  738. * @return SchemaConfig
  739. */
  740. public function createSchemaConfig()
  741. {
  742. $schemaConfig = new SchemaConfig();
  743. $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
  744. $searchPaths = $this->getSchemaSearchPaths();
  745. if (isset($searchPaths[0])) {
  746. $schemaConfig->setName($searchPaths[0]);
  747. }
  748. return $schemaConfig;
  749. }
  750. /**
  751. * The search path for namespaces in the currently connected database.
  752. *
  753. * The first entry is usually the default namespace in the Schema. All
  754. * further namespaces contain tables/sequences which can also be addressed
  755. * with a short, not full-qualified name.
  756. *
  757. * For databases that don't support subschema/namespaces this method
  758. * returns the name of the currently connected database.
  759. *
  760. * @return array
  761. */
  762. public function getSchemaSearchPaths()
  763. {
  764. return array($this->_conn->getDatabase());
  765. }
  766. /**
  767. * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
  768. * the type given as default.
  769. *
  770. * @param string $comment
  771. * @param string $currentType
  772. * @return string
  773. */
  774. public function extractDoctrineTypeFromComment($comment, $currentType)
  775. {
  776. if (preg_match("(\(DC2Type:([a-zA-Z0-9]+)\))", $comment, $match)) {
  777. $currentType = $match[1];
  778. }
  779. return $currentType;
  780. }
  781. public function removeDoctrineTypeFromComment($comment, $type)
  782. {
  783. return str_replace('(DC2Type:'.$type.')', '', $comment);
  784. }
  785. }