vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php line 314

Open in your IDE?
  1. <?php
  2. namespace Doctrine\DBAL\Schema;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
  5. use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
  6. use Doctrine\DBAL\Events;
  7. use Doctrine\DBAL\Exception;
  8. use Doctrine\DBAL\Exception\DatabaseRequired;
  9. use Doctrine\DBAL\Platforms\AbstractPlatform;
  10. use Doctrine\DBAL\Result;
  11. use Doctrine\Deprecations\Deprecation;
  12. use Throwable;
  13. use function array_filter;
  14. use function array_intersect;
  15. use function array_map;
  16. use function array_values;
  17. use function assert;
  18. use function call_user_func_array;
  19. use function count;
  20. use function func_get_args;
  21. use function is_callable;
  22. use function is_string;
  23. use function preg_match;
  24. use function str_replace;
  25. use function strtolower;
  26. /**
  27.  * Base class for schema managers. Schema managers are used to inspect and/or
  28.  * modify the database schema/structure.
  29.  *
  30.  * @template T of AbstractPlatform
  31.  */
  32. abstract class AbstractSchemaManager
  33. {
  34.     /**
  35.      * Holds instance of the Doctrine connection for this schema manager.
  36.      *
  37.      * @var Connection
  38.      */
  39.     protected $_conn;
  40.     /**
  41.      * Holds instance of the database platform used for this schema manager.
  42.      *
  43.      * @var T
  44.      */
  45.     protected $_platform;
  46.     /**
  47.      * @param T $platform
  48.      */
  49.     public function __construct(Connection $connectionAbstractPlatform $platform)
  50.     {
  51.         $this->_conn     $connection;
  52.         $this->_platform $platform;
  53.     }
  54.     /**
  55.      * Returns the associated platform.
  56.      *
  57.      * @deprecated Use {@link Connection::getDatabasePlatform()} instead.
  58.      *
  59.      * @return T
  60.      */
  61.     public function getDatabasePlatform()
  62.     {
  63.         Deprecation::trigger(
  64.             'doctrine/dbal',
  65.             'https://github.com/doctrine/dbal/pull/5387',
  66.             'AbstractSchemaManager::getDatabasePlatform() is deprecated.'
  67.                 ' Use Connection::getDatabasePlatform() instead.'
  68.         );
  69.         return $this->_platform;
  70.     }
  71.     /**
  72.      * Tries 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.      * @deprecated
  82.      *
  83.      * @return mixed
  84.      */
  85.     public function tryMethod()
  86.     {
  87.         Deprecation::triggerIfCalledFromOutside(
  88.             'doctrine/dbal',
  89.             'https://github.com/doctrine/dbal/pull/4897',
  90.             'AbstractSchemaManager::tryMethod() is deprecated.'
  91.         );
  92.         $args   func_get_args();
  93.         $method $args[0];
  94.         unset($args[0]);
  95.         $args array_values($args);
  96.         $callback = [$this$method];
  97.         assert(is_callable($callback));
  98.         try {
  99.             return call_user_func_array($callback$args);
  100.         } catch (Throwable $e) {
  101.             return false;
  102.         }
  103.     }
  104.     /**
  105.      * Lists the available databases for this connection.
  106.      *
  107.      * @return string[]
  108.      *
  109.      * @throws Exception
  110.      */
  111.     public function listDatabases()
  112.     {
  113.         $sql $this->_platform->getListDatabasesSQL();
  114.         $databases $this->_conn->fetchAllAssociative($sql);
  115.         return $this->_getPortableDatabasesList($databases);
  116.     }
  117.     /**
  118.      * Returns a list of all namespaces in the current database.
  119.      *
  120.      * @deprecated Use {@see listSchemaNames()} instead.
  121.      *
  122.      * @return string[]
  123.      *
  124.      * @throws Exception
  125.      */
  126.     public function listNamespaceNames()
  127.     {
  128.         Deprecation::triggerIfCalledFromOutside(
  129.             'doctrine/dbal',
  130.             'https://github.com/doctrine/dbal/issues/4503',
  131.             'AbstractSchemaManager::listNamespaceNames() is deprecated,'
  132.                 ' use AbstractSchemaManager::listSchemaNames() instead.'
  133.         );
  134.         $sql $this->_platform->getListNamespacesSQL();
  135.         $namespaces $this->_conn->fetchAllAssociative($sql);
  136.         return $this->getPortableNamespacesList($namespaces);
  137.     }
  138.     /**
  139.      * Returns a list of the names of all schemata in the current database.
  140.      *
  141.      * @return list<string>
  142.      *
  143.      * @throws Exception
  144.      */
  145.     public function listSchemaNames(): array
  146.     {
  147.         throw Exception::notSupported(__METHOD__);
  148.     }
  149.     /**
  150.      * Lists the available sequences for this connection.
  151.      *
  152.      * @param string|null $database
  153.      *
  154.      * @return Sequence[]
  155.      *
  156.      * @throws Exception
  157.      */
  158.     public function listSequences($database null)
  159.     {
  160.         if ($database === null) {
  161.             $database $this->getDatabase(__METHOD__);
  162.         } else {
  163.             Deprecation::trigger(
  164.                 'doctrine/dbal',
  165.                 'https://github.com/doctrine/dbal/issues/5284',
  166.                 'Passing $database to AbstractSchemaManager::listSequences() is deprecated.'
  167.             );
  168.         }
  169.         $sql $this->_platform->getListSequencesSQL($database);
  170.         $sequences $this->_conn->fetchAllAssociative($sql);
  171.         return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
  172.     }
  173.     /**
  174.      * Lists the columns for a given table.
  175.      *
  176.      * In contrast to other libraries and to the old version of Doctrine,
  177.      * this column definition does try to contain the 'primary' column for
  178.      * the reason that it is not portable across different RDBMS. Use
  179.      * {@see listTableIndexes($tableName)} to retrieve the primary key
  180.      * of a table. Where a RDBMS specifies more details, these are held
  181.      * in the platformDetails array.
  182.      *
  183.      * @param string      $table    The name of the table.
  184.      * @param string|null $database
  185.      *
  186.      * @return Column[]
  187.      *
  188.      * @throws Exception
  189.      */
  190.     public function listTableColumns($table$database null)
  191.     {
  192.         if ($database === null) {
  193.             $database $this->getDatabase(__METHOD__);
  194.         } else {
  195.             Deprecation::trigger(
  196.                 'doctrine/dbal',
  197.                 'https://github.com/doctrine/dbal/issues/5284',
  198.                 'Passing $database to AbstractSchemaManager::listTableColumns() is deprecated.'
  199.             );
  200.         }
  201.         $sql $this->_platform->getListTableColumnsSQL($table$database);
  202.         $tableColumns $this->_conn->fetchAllAssociative($sql);
  203.         return $this->_getPortableTableColumnList($table$database$tableColumns);
  204.     }
  205.     /**
  206.      * @param string      $table
  207.      * @param string|null $database
  208.      *
  209.      * @return Column[]
  210.      *
  211.      * @throws Exception
  212.      */
  213.     protected function doListTableColumns($table$database null): array
  214.     {
  215.         if ($database === null) {
  216.             $database $this->getDatabase(__METHOD__);
  217.         } else {
  218.             Deprecation::trigger(
  219.                 'doctrine/dbal',
  220.                 'https://github.com/doctrine/dbal/issues/5284',
  221.                 'Passing $database to AbstractSchemaManager::listTableColumns() is deprecated.'
  222.             );
  223.         }
  224.         return $this->_getPortableTableColumnList(
  225.             $table,
  226.             $database,
  227.             $this->selectTableColumns($database$this->normalizeName($table))
  228.                 ->fetchAllAssociative()
  229.         );
  230.     }
  231.     /**
  232.      * Lists the indexes for a given table returning an array of Index instances.
  233.      *
  234.      * Keys of the portable indexes list are all lower-cased.
  235.      *
  236.      * @param string $table The name of the table.
  237.      *
  238.      * @return Index[]
  239.      *
  240.      * @throws Exception
  241.      */
  242.     public function listTableIndexes($table)
  243.     {
  244.         $sql $this->_platform->getListTableIndexesSQL($table$this->_conn->getDatabase());
  245.         $tableIndexes $this->_conn->fetchAllAssociative($sql);
  246.         return $this->_getPortableTableIndexesList($tableIndexes$table);
  247.     }
  248.     /**
  249.      * @param string $table
  250.      *
  251.      * @return Index[]
  252.      *
  253.      * @throws Exception
  254.      */
  255.     protected function doListTableIndexes($table): array
  256.     {
  257.         $database $this->getDatabase(__METHOD__);
  258.         $table    $this->normalizeName($table);
  259.         return $this->_getPortableTableIndexesList(
  260.             $this->selectIndexColumns(
  261.                 $database,
  262.                 $table
  263.             )->fetchAllAssociative(),
  264.             $table
  265.         );
  266.     }
  267.     /**
  268.      * Returns true if all the given tables exist.
  269.      *
  270.      * The usage of a string $tableNames is deprecated. Pass a one-element array instead.
  271.      *
  272.      * @param string|string[] $names
  273.      *
  274.      * @return bool
  275.      *
  276.      * @throws Exception
  277.      */
  278.     public function tablesExist($names)
  279.     {
  280.         if (is_string($names)) {
  281.             Deprecation::trigger(
  282.                 'doctrine/dbal',
  283.                 'https://github.com/doctrine/dbal/issues/3580',
  284.                 'The usage of a string $tableNames in AbstractSchemaManager::tablesExist() is deprecated. ' .
  285.                 'Pass a one-element array instead.'
  286.             );
  287.         }
  288.         $names array_map('strtolower', (array) $names);
  289.         return count($names) === count(array_intersect($namesarray_map('strtolower'$this->listTableNames())));
  290.     }
  291.     /**
  292.      * Returns a list of all tables in the current database.
  293.      *
  294.      * @return string[]
  295.      *
  296.      * @throws Exception
  297.      */
  298.     public function listTableNames()
  299.     {
  300.         $sql $this->_platform->getListTablesSQL();
  301.         $tables     $this->_conn->fetchAllAssociative($sql);
  302.         $tableNames $this->_getPortableTablesList($tables);
  303.         return $this->filterAssetNames($tableNames);
  304.     }
  305.     /**
  306.      * @return list<string>
  307.      *
  308.      * @throws Exception
  309.      */
  310.     protected function doListTableNames(): array
  311.     {
  312.         $database $this->getDatabase(__METHOD__);
  313.         return $this->filterAssetNames(
  314.             $this->_getPortableTablesList(
  315.                 $this->selectTableNames($database)
  316.                     ->fetchAllAssociative()
  317.             )
  318.         );
  319.     }
  320.     /**
  321.      * Filters asset names if they are configured to return only a subset of all
  322.      * the found elements.
  323.      *
  324.      * @param mixed[] $assetNames
  325.      *
  326.      * @return mixed[]
  327.      */
  328.     protected function filterAssetNames($assetNames)
  329.     {
  330.         $filter $this->_conn->getConfiguration()->getSchemaAssetsFilter();
  331.         if ($filter === null) {
  332.             return $assetNames;
  333.         }
  334.         return array_values(array_filter($assetNames$filter));
  335.     }
  336.     /**
  337.      * Lists the tables for this connection.
  338.      *
  339.      * @return list<Table>
  340.      *
  341.      * @throws Exception
  342.      */
  343.     public function listTables()
  344.     {
  345.         $tableNames $this->listTableNames();
  346.         $tables = [];
  347.         foreach ($tableNames as $tableName) {
  348.             $tables[] = $this->listTableDetails($tableName);
  349.         }
  350.         return $tables;
  351.     }
  352.     /**
  353.      * @return list<Table>
  354.      *
  355.      * @throws Exception
  356.      */
  357.     protected function doListTables(): array
  358.     {
  359.         $database $this->getDatabase(__METHOD__);
  360.         $tableColumnsByTable      $this->fetchTableColumnsByTable($database);
  361.         $indexColumnsByTable      $this->fetchIndexColumnsByTable($database);
  362.         $foreignKeyColumnsByTable $this->fetchForeignKeyColumnsByTable($database);
  363.         $tableOptionsByTable      $this->fetchTableOptionsByTable($database);
  364.         $filter $this->_conn->getConfiguration()->getSchemaAssetsFilter();
  365.         $tables = [];
  366.         foreach ($tableColumnsByTable as $tableName => $tableColumns) {
  367.             if ($filter !== null && ! $filter($tableName)) {
  368.                 continue;
  369.             }
  370.             $tables[] = new Table(
  371.                 $tableName,
  372.                 $this->_getPortableTableColumnList($tableName$database$tableColumns),
  373.                 $this->_getPortableTableIndexesList($indexColumnsByTable[$tableName] ?? [], $tableName),
  374.                 [],
  375.                 $this->_getPortableTableForeignKeysList($foreignKeyColumnsByTable[$tableName] ?? []),
  376.                 $tableOptionsByTable[$tableName] ?? []
  377.             );
  378.         }
  379.         return $tables;
  380.     }
  381.     /**
  382.      * @param string $name
  383.      *
  384.      * @return Table
  385.      *
  386.      * @throws Exception
  387.      */
  388.     public function listTableDetails($name)
  389.     {
  390.         $columns     $this->listTableColumns($name);
  391.         $foreignKeys = [];
  392.         if ($this->_platform->supportsForeignKeyConstraints()) {
  393.             $foreignKeys $this->listTableForeignKeys($name);
  394.         }
  395.         $indexes $this->listTableIndexes($name);
  396.         return new Table($name$columns$indexes, [], $foreignKeys);
  397.     }
  398.     /**
  399.      * @param string $name
  400.      *
  401.      * @throws Exception
  402.      */
  403.     protected function doListTableDetails($name): Table
  404.     {
  405.         $database $this->getDatabase(__METHOD__);
  406.         $normalizedName $this->normalizeName($name);
  407.         $tableOptionsByTable $this->fetchTableOptionsByTable($database$normalizedName);
  408.         if ($this->_platform->supportsForeignKeyConstraints()) {
  409.             $foreignKeys $this->listTableForeignKeys($name);
  410.         } else {
  411.             $foreignKeys = [];
  412.         }
  413.         return new Table(
  414.             $name,
  415.             $this->listTableColumns($name$database),
  416.             $this->listTableIndexes($name),
  417.             [],
  418.             $foreignKeys,
  419.             $tableOptionsByTable[$normalizedName] ?? []
  420.         );
  421.     }
  422.     /**
  423.      * An extension point for those platforms where case sensitivity of the object name depends on whether it's quoted.
  424.      *
  425.      * Such platforms should convert a possibly quoted name into a value of the corresponding case.
  426.      */
  427.     protected function normalizeName(string $name): string
  428.     {
  429.         $identifier = new Identifier($name);
  430.         return $identifier->getName();
  431.     }
  432.     /**
  433.      * Selects names of tables in the specified database.
  434.      *
  435.      * @throws Exception
  436.      *
  437.      * @abstract
  438.      */
  439.     protected function selectTableNames(string $databaseName): Result
  440.     {
  441.         throw Exception::notSupported(__METHOD__);
  442.     }
  443.     /**
  444.      * Selects definitions of table columns in the specified database. If the table name is specified, narrows down
  445.      * the selection to this table.
  446.      *
  447.      * @throws Exception
  448.      *
  449.      * @abstract
  450.      */
  451.     protected function selectTableColumns(string $databaseName, ?string $tableName null): Result
  452.     {
  453.         throw Exception::notSupported(__METHOD__);
  454.     }
  455.     /**
  456.      * Selects definitions of index columns in the specified database. If the table name is specified, narrows down
  457.      * the selection to this table.
  458.      *
  459.      * @throws Exception
  460.      */
  461.     protected function selectIndexColumns(string $databaseName, ?string $tableName null): Result
  462.     {
  463.         throw Exception::notSupported(__METHOD__);
  464.     }
  465.     /**
  466.      * Selects definitions of foreign key columns in the specified database. If the table name is specified,
  467.      * narrows down the selection to this table.
  468.      *
  469.      * @throws Exception
  470.      */
  471.     protected function selectForeignKeyColumns(string $databaseName, ?string $tableName null): Result
  472.     {
  473.         throw Exception::notSupported(__METHOD__);
  474.     }
  475.     /**
  476.      * Fetches definitions of table columns in the specified database and returns them grouped by table name.
  477.      *
  478.      * @return array<string,list<array<string,mixed>>>
  479.      *
  480.      * @throws Exception
  481.      */
  482.     protected function fetchTableColumnsByTable(string $databaseName): array
  483.     {
  484.         return $this->fetchAllAssociativeGrouped($this->selectTableColumns($databaseName));
  485.     }
  486.     /**
  487.      * Fetches definitions of index columns in the specified database and returns them grouped by table name.
  488.      *
  489.      * @return array<string,list<array<string,mixed>>>
  490.      *
  491.      * @throws Exception
  492.      */
  493.     protected function fetchIndexColumnsByTable(string $databaseName): array
  494.     {
  495.         return $this->fetchAllAssociativeGrouped($this->selectIndexColumns($databaseName));
  496.     }
  497.     /**
  498.      * Fetches definitions of foreign key columns in the specified database and returns them grouped by table name.
  499.      *
  500.      * @return array<string, list<array<string, mixed>>>
  501.      *
  502.      * @throws Exception
  503.      */
  504.     protected function fetchForeignKeyColumnsByTable(string $databaseName): array
  505.     {
  506.         if (! $this->_platform->supportsForeignKeyConstraints()) {
  507.             return [];
  508.         }
  509.         return $this->fetchAllAssociativeGrouped(
  510.             $this->selectForeignKeyColumns($databaseName)
  511.         );
  512.     }
  513.     /**
  514.      * Fetches table options for the tables in the specified database and returns them grouped by table name.
  515.      * If the table name is specified, narrows down the selection to this table.
  516.      *
  517.      * @return array<string,array<string,mixed>>
  518.      *
  519.      * @throws Exception
  520.      */
  521.     protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName null): array
  522.     {
  523.         throw Exception::notSupported(__METHOD__);
  524.     }
  525.     /**
  526.      * Lists the views this connection has.
  527.      *
  528.      * @return View[]
  529.      *
  530.      * @throws Exception
  531.      */
  532.     public function listViews()
  533.     {
  534.         $database $this->_conn->getDatabase();
  535.         $sql      $this->_platform->getListViewsSQL($database);
  536.         $views    $this->_conn->fetchAllAssociative($sql);
  537.         return $this->_getPortableViewsList($views);
  538.     }
  539.     /**
  540.      * Lists the foreign keys for the given table.
  541.      *
  542.      * @param string      $table    The name of the table.
  543.      * @param string|null $database
  544.      *
  545.      * @return ForeignKeyConstraint[]
  546.      *
  547.      * @throws Exception
  548.      */
  549.     public function listTableForeignKeys($table$database null)
  550.     {
  551.         if ($database === null) {
  552.             $database $this->getDatabase(__METHOD__);
  553.         } else {
  554.             Deprecation::trigger(
  555.                 'doctrine/dbal',
  556.                 'https://github.com/doctrine/dbal/issues/5284',
  557.                 'Passing $database to AbstractSchemaManager::listTableForeignKeys() is deprecated.'
  558.             );
  559.         }
  560.         $sql              $this->_platform->getListTableForeignKeysSQL($table$database);
  561.         $tableForeignKeys $this->_conn->fetchAllAssociative($sql);
  562.         return $this->_getPortableTableForeignKeysList($tableForeignKeys);
  563.     }
  564.     /**
  565.      * @param string      $table
  566.      * @param string|null $database
  567.      *
  568.      * @return ForeignKeyConstraint[]
  569.      *
  570.      * @throws Exception
  571.      */
  572.     protected function doListTableForeignKeys($table$database null): array
  573.     {
  574.         if ($database === null) {
  575.             $database $this->getDatabase(__METHOD__);
  576.         } else {
  577.             Deprecation::trigger(
  578.                 'doctrine/dbal',
  579.                 'https://github.com/doctrine/dbal/issues/5284',
  580.                 'Passing $database to AbstractSchemaManager::listTableForeignKeys() is deprecated.'
  581.             );
  582.         }
  583.         return $this->_getPortableTableForeignKeysList(
  584.             $this->selectForeignKeyColumns(
  585.                 $database,
  586.                 $this->normalizeName($table)
  587.             )->fetchAllAssociative()
  588.         );
  589.     }
  590.     /* drop*() Methods */
  591.     /**
  592.      * Drops a database.
  593.      *
  594.      * NOTE: You can not drop the database this SchemaManager is currently connected to.
  595.      *
  596.      * @param string $database The name of the database to drop.
  597.      *
  598.      * @return void
  599.      *
  600.      * @throws Exception
  601.      */
  602.     public function dropDatabase($database)
  603.     {
  604.         $this->_execSql($this->_platform->getDropDatabaseSQL($database));
  605.     }
  606.     /**
  607.      * Drops a schema.
  608.      *
  609.      * @throws Exception
  610.      */
  611.     public function dropSchema(string $schemaName): void
  612.     {
  613.         $this->_execSql($this->_platform->getDropSchemaSQL($schemaName));
  614.     }
  615.     /**
  616.      * Drops the given table.
  617.      *
  618.      * @param string $name The name of the table to drop.
  619.      *
  620.      * @return void
  621.      *
  622.      * @throws Exception
  623.      */
  624.     public function dropTable($name)
  625.     {
  626.         $this->_execSql($this->_platform->getDropTableSQL($name));
  627.     }
  628.     /**
  629.      * Drops the index from the given table.
  630.      *
  631.      * @param Index|string $index The name of the index.
  632.      * @param Table|string $table The name of the table.
  633.      *
  634.      * @return void
  635.      *
  636.      * @throws Exception
  637.      */
  638.     public function dropIndex($index$table)
  639.     {
  640.         if ($index instanceof Index) {
  641.             Deprecation::trigger(
  642.                 'doctrine/dbal',
  643.                 'https://github.com/doctrine/dbal/issues/4798',
  644.                 'Passing $index as an Index object to %s is deprecated. Pass it as a quoted name instead.',
  645.                 __METHOD__
  646.             );
  647.             $index $index->getQuotedName($this->_platform);
  648.         }
  649.         if ($table instanceof Table) {
  650.             Deprecation::trigger(
  651.                 'doctrine/dbal',
  652.                 'https://github.com/doctrine/dbal/issues/4798',
  653.                 'Passing $table as an Table object to %s is deprecated. Pass it as a quoted name instead.',
  654.                 __METHOD__
  655.             );
  656.             $table $table->getQuotedName($this->_platform);
  657.         }
  658.         $this->_execSql($this->_platform->getDropIndexSQL($index$table));
  659.     }
  660.     /**
  661.      * Drops the constraint from the given table.
  662.      *
  663.      * @deprecated Use {@see dropIndex()}, {@see dropForeignKey()} or {@see dropUniqueConstraint()} instead.
  664.      *
  665.      * @param Table|string $table The name of the table.
  666.      *
  667.      * @return void
  668.      *
  669.      * @throws Exception
  670.      */
  671.     public function dropConstraint(Constraint $constraint$table)
  672.     {
  673.         if ($table instanceof Table) {
  674.             Deprecation::trigger(
  675.                 'doctrine/dbal',
  676.                 'https://github.com/doctrine/dbal/issues/4798',
  677.                 'Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.',
  678.                 __METHOD__
  679.             );
  680.             $table $table->getQuotedName($this->_platform);
  681.         }
  682.         $this->_execSql($this->_platform->getDropConstraintSQL(
  683.             $constraint->getQuotedName($this->_platform),
  684.             $table
  685.         ));
  686.     }
  687.     /**
  688.      * Drops a foreign key from a table.
  689.      *
  690.      * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
  691.      * @param Table|string                $table      The name of the table with the foreign key.
  692.      *
  693.      * @return void
  694.      *
  695.      * @throws Exception
  696.      */
  697.     public function dropForeignKey($foreignKey$table)
  698.     {
  699.         if ($foreignKey instanceof ForeignKeyConstraint) {
  700.             Deprecation::trigger(
  701.                 'doctrine/dbal',
  702.                 'https://github.com/doctrine/dbal/issues/4798',
  703.                 'Passing $foreignKey as a ForeignKeyConstraint object to %s is deprecated.'
  704.                 ' Pass it as a quoted name instead.',
  705.                 __METHOD__
  706.             );
  707.             $foreignKey $foreignKey->getQuotedName($this->_platform);
  708.         }
  709.         if ($table instanceof Table) {
  710.             Deprecation::trigger(
  711.                 'doctrine/dbal',
  712.                 'https://github.com/doctrine/dbal/issues/4798',
  713.                 'Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.',
  714.                 __METHOD__
  715.             );
  716.             $table $table->getQuotedName($this->_platform);
  717.         }
  718.         $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey$table));
  719.     }
  720.     /**
  721.      * Drops a sequence with a given name.
  722.      *
  723.      * @param string $name The name of the sequence to drop.
  724.      *
  725.      * @return void
  726.      *
  727.      * @throws Exception
  728.      */
  729.     public function dropSequence($name)
  730.     {
  731.         $this->_execSql($this->_platform->getDropSequenceSQL($name));
  732.     }
  733.     /**
  734.      * Drops the unique constraint from the given table.
  735.      *
  736.      * @throws Exception
  737.      */
  738.     public function dropUniqueConstraint(string $namestring $tableName): void
  739.     {
  740.         $this->_execSql($this->_platform->getDropUniqueConstraintSQL($name$tableName));
  741.     }
  742.     /**
  743.      * Drops a view.
  744.      *
  745.      * @param string $name The name of the view.
  746.      *
  747.      * @return void
  748.      *
  749.      * @throws Exception
  750.      */
  751.     public function dropView($name)
  752.     {
  753.         $this->_execSql($this->_platform->getDropViewSQL($name));
  754.     }
  755.     /* create*() Methods */
  756.     /**
  757.      * @throws Exception
  758.      */
  759.     public function createSchemaObjects(Schema $schema): void
  760.     {
  761.         $this->_execSql($schema->toSql($this->_platform));
  762.     }
  763.     /**
  764.      * Creates a new database.
  765.      *
  766.      * @param string $database The name of the database to create.
  767.      *
  768.      * @return void
  769.      *
  770.      * @throws Exception
  771.      */
  772.     public function createDatabase($database)
  773.     {
  774.         $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
  775.     }
  776.     /**
  777.      * Creates a new table.
  778.      *
  779.      * @return void
  780.      *
  781.      * @throws Exception
  782.      */
  783.     public function createTable(Table $table)
  784.     {
  785.         $createFlags AbstractPlatform::CREATE_INDEXES AbstractPlatform::CREATE_FOREIGNKEYS;
  786.         $this->_execSql($this->_platform->getCreateTableSQL($table$createFlags));
  787.     }
  788.     /**
  789.      * Creates a new sequence.
  790.      *
  791.      * @param Sequence $sequence
  792.      *
  793.      * @return void
  794.      *
  795.      * @throws Exception
  796.      */
  797.     public function createSequence($sequence)
  798.     {
  799.         $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
  800.     }
  801.     /**
  802.      * Creates a constraint on a table.
  803.      *
  804.      * @deprecated Use {@see createIndex()}, {@see createForeignKey()} or {@see createUniqueConstraint()} instead.
  805.      *
  806.      * @param Table|string $table
  807.      *
  808.      * @return void
  809.      *
  810.      * @throws Exception
  811.      */
  812.     public function createConstraint(Constraint $constraint$table)
  813.     {
  814.         $this->_execSql($this->_platform->getCreateConstraintSQL($constraint$table));
  815.     }
  816.     /**
  817.      * Creates a new index on a table.
  818.      *
  819.      * @param Table|string $table The name of the table on which the index is to be created.
  820.      *
  821.      * @return void
  822.      *
  823.      * @throws Exception
  824.      */
  825.     public function createIndex(Index $index$table)
  826.     {
  827.         $this->_execSql($this->_platform->getCreateIndexSQL($index$table));
  828.     }
  829.     /**
  830.      * Creates a new foreign key.
  831.      *
  832.      * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
  833.      * @param Table|string         $table      The name of the table on which the foreign key is to be created.
  834.      *
  835.      * @return void
  836.      *
  837.      * @throws Exception
  838.      */
  839.     public function createForeignKey(ForeignKeyConstraint $foreignKey$table)
  840.     {
  841.         $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey$table));
  842.     }
  843.     /**
  844.      * Creates a unique constraint on a table.
  845.      *
  846.      * @throws Exception
  847.      */
  848.     public function createUniqueConstraint(UniqueConstraint $uniqueConstraintstring $tableName): void
  849.     {
  850.         $this->_execSql($this->_platform->getCreateUniqueConstraintSQL($uniqueConstraint$tableName));
  851.     }
  852.     /**
  853.      * Creates a new view.
  854.      *
  855.      * @return void
  856.      *
  857.      * @throws Exception
  858.      */
  859.     public function createView(View $view)
  860.     {
  861.         $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
  862.     }
  863.     /* dropAndCreate*() Methods */
  864.     /**
  865.      * @throws Exception
  866.      */
  867.     public function dropSchemaObjects(Schema $schema): void
  868.     {
  869.         $this->_execSql($schema->toDropSql($this->_platform));
  870.     }
  871.     /**
  872.      * Drops and creates a constraint.
  873.      *
  874.      * @deprecated Use {@see dropIndex()} and {@see createIndex()},
  875.      *             {@see dropForeignKey()} and {@see createForeignKey()}
  876.      *             or {@see dropUniqueConstraint()} and {@see createUniqueConstraint()} instead.
  877.      *
  878.      * @see dropConstraint()
  879.      * @see createConstraint()
  880.      *
  881.      * @param Table|string $table
  882.      *
  883.      * @return void
  884.      *
  885.      * @throws Exception
  886.      */
  887.     public function dropAndCreateConstraint(Constraint $constraint$table)
  888.     {
  889.         Deprecation::trigger(
  890.             'doctrine/dbal',
  891.             'https://github.com/doctrine/dbal/pull/4897',
  892.             'AbstractSchemaManager::dropAndCreateConstraint() is deprecated.'
  893.                 ' Use AbstractSchemaManager::dropIndex() and AbstractSchemaManager::createIndex(),'
  894.                 ' AbstractSchemaManager::dropForeignKey() and AbstractSchemaManager::createForeignKey()'
  895.                 ' or AbstractSchemaManager::dropUniqueConstraint()'
  896.                 ' and AbstractSchemaManager::createUniqueConstraint() instead.'
  897.         );
  898.         $this->tryMethod('dropConstraint'$constraint$table);
  899.         $this->createConstraint($constraint$table);
  900.     }
  901.     /**
  902.      * Drops and creates a new index on a table.
  903.      *
  904.      * @deprecated Use {@see dropIndex()} and {@see createIndex()} instead.
  905.      *
  906.      * @param Table|string $table The name of the table on which the index is to be created.
  907.      *
  908.      * @return void
  909.      *
  910.      * @throws Exception
  911.      */
  912.     public function dropAndCreateIndex(Index $index$table)
  913.     {
  914.         Deprecation::trigger(
  915.             'doctrine/dbal',
  916.             'https://github.com/doctrine/dbal/pull/4897',
  917.             'AbstractSchemaManager::dropAndCreateIndex() is deprecated.'
  918.             ' Use AbstractSchemaManager::dropIndex() and AbstractSchemaManager::createIndex() instead.'
  919.         );
  920.         $this->tryMethod('dropIndex'$index->getQuotedName($this->_platform), $table);
  921.         $this->createIndex($index$table);
  922.     }
  923.     /**
  924.      * Drops and creates a new foreign key.
  925.      *
  926.      * @deprecated Use {@see dropForeignKey()} and {@see createForeignKey()} instead.
  927.      *
  928.      * @param ForeignKeyConstraint $foreignKey An associative array that defines properties
  929.      *                                         of the foreign key to be created.
  930.      * @param Table|string         $table      The name of the table on which the foreign key is to be created.
  931.      *
  932.      * @return void
  933.      *
  934.      * @throws Exception
  935.      */
  936.     public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey$table)
  937.     {
  938.         Deprecation::trigger(
  939.             'doctrine/dbal',
  940.             'https://github.com/doctrine/dbal/pull/4897',
  941.             'AbstractSchemaManager::dropAndCreateForeignKey() is deprecated.'
  942.             ' Use AbstractSchemaManager::dropForeignKey() and AbstractSchemaManager::createForeignKey() instead.'
  943.         );
  944.         $this->tryMethod('dropForeignKey'$foreignKey$table);
  945.         $this->createForeignKey($foreignKey$table);
  946.     }
  947.     /**
  948.      * Drops and create a new sequence.
  949.      *
  950.      * @deprecated Use {@see dropSequence()} and {@see createSequence()} instead.
  951.      *
  952.      * @return void
  953.      *
  954.      * @throws Exception
  955.      */
  956.     public function dropAndCreateSequence(Sequence $sequence)
  957.     {
  958.         Deprecation::trigger(
  959.             'doctrine/dbal',
  960.             'https://github.com/doctrine/dbal/pull/4897',
  961.             'AbstractSchemaManager::dropAndCreateSequence() is deprecated.'
  962.             ' Use AbstractSchemaManager::dropSequence() and AbstractSchemaManager::createSequence() instead.'
  963.         );
  964.         $this->tryMethod('dropSequence'$sequence->getQuotedName($this->_platform));
  965.         $this->createSequence($sequence);
  966.     }
  967.     /**
  968.      * Drops and creates a new table.
  969.      *
  970.      * @deprecated Use {@see dropTable()} and {@see createTable()} instead.
  971.      *
  972.      * @return void
  973.      *
  974.      * @throws Exception
  975.      */
  976.     public function dropAndCreateTable(Table $table)
  977.     {
  978.         Deprecation::trigger(
  979.             'doctrine/dbal',
  980.             'https://github.com/doctrine/dbal/pull/4897',
  981.             'AbstractSchemaManager::dropAndCreateTable() is deprecated.'
  982.             ' Use AbstractSchemaManager::dropTable() and AbstractSchemaManager::createTable() instead.'
  983.         );
  984.         $this->tryMethod('dropTable'$table->getQuotedName($this->_platform));
  985.         $this->createTable($table);
  986.     }
  987.     /**
  988.      * Drops and creates a new database.
  989.      *
  990.      * @deprecated Use {@see dropDatabase()} and {@see createDatabase()} instead.
  991.      *
  992.      * @param string $database The name of the database to create.
  993.      *
  994.      * @return void
  995.      *
  996.      * @throws Exception
  997.      */
  998.     public function dropAndCreateDatabase($database)
  999.     {
  1000.         Deprecation::trigger(
  1001.             'doctrine/dbal',
  1002.             'https://github.com/doctrine/dbal/pull/4897',
  1003.             'AbstractSchemaManager::dropAndCreateDatabase() is deprecated.'
  1004.             ' Use AbstractSchemaManager::dropDatabase() and AbstractSchemaManager::createDatabase() instead.'
  1005.         );
  1006.         $this->tryMethod('dropDatabase'$database);
  1007.         $this->createDatabase($database);
  1008.     }
  1009.     /**
  1010.      * Drops and creates a new view.
  1011.      *
  1012.      * @deprecated Use {@see dropView()} and {@see createView()} instead.
  1013.      *
  1014.      * @return void
  1015.      *
  1016.      * @throws Exception
  1017.      */
  1018.     public function dropAndCreateView(View $view)
  1019.     {
  1020.         Deprecation::trigger(
  1021.             'doctrine/dbal',
  1022.             'https://github.com/doctrine/dbal/pull/4897',
  1023.             'AbstractSchemaManager::dropAndCreateView() is deprecated.'
  1024.             ' Use AbstractSchemaManager::dropView() and AbstractSchemaManager::createView() instead.'
  1025.         );
  1026.         $this->tryMethod('dropView'$view->getQuotedName($this->_platform));
  1027.         $this->createView($view);
  1028.     }
  1029.     /**
  1030.      * Alters an existing schema.
  1031.      *
  1032.      * @throws Exception
  1033.      */
  1034.     public function alterSchema(SchemaDiff $schemaDiff): void
  1035.     {
  1036.         $this->_execSql($schemaDiff->toSql($this->_platform));
  1037.     }
  1038.     /**
  1039.      * Migrates an existing schema to a new schema.
  1040.      *
  1041.      * @throws Exception
  1042.      */
  1043.     public function migrateSchema(Schema $toSchema): void
  1044.     {
  1045.         $schemaDiff $this->createComparator()
  1046.             ->compareSchemas($this->createSchema(), $toSchema);
  1047.         $this->alterSchema($schemaDiff);
  1048.     }
  1049.     /* alterTable() Methods */
  1050.     /**
  1051.      * Alters an existing tables schema.
  1052.      *
  1053.      * @return void
  1054.      *
  1055.      * @throws Exception
  1056.      */
  1057.     public function alterTable(TableDiff $tableDiff)
  1058.     {
  1059.         foreach ($this->_platform->getAlterTableSQL($tableDiff) as $ddlQuery) {
  1060.             $this->_execSql($ddlQuery);
  1061.         }
  1062.     }
  1063.     /**
  1064.      * Renames a given table to another name.
  1065.      *
  1066.      * @param string $name    The current name of the table.
  1067.      * @param string $newName The new name of the table.
  1068.      *
  1069.      * @return void
  1070.      *
  1071.      * @throws Exception
  1072.      */
  1073.     public function renameTable($name$newName)
  1074.     {
  1075.         $tableDiff          = new TableDiff($name);
  1076.         $tableDiff->newName $newName;
  1077.         $this->alterTable($tableDiff);
  1078.     }
  1079.     /**
  1080.      * Methods for filtering return values of list*() methods to convert
  1081.      * the native DBMS data definition to a portable Doctrine definition
  1082.      */
  1083.     /**
  1084.      * @param mixed[] $databases
  1085.      *
  1086.      * @return string[]
  1087.      */
  1088.     protected function _getPortableDatabasesList($databases)
  1089.     {
  1090.         $list = [];
  1091.         foreach ($databases as $value) {
  1092.             $list[] = $this->_getPortableDatabaseDefinition($value);
  1093.         }
  1094.         return $list;
  1095.     }
  1096.     /**
  1097.      * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
  1098.      *
  1099.      * @deprecated Use {@see listSchemaNames()} instead.
  1100.      *
  1101.      * @param array<int, array<string, mixed>> $namespaces The list of namespace names
  1102.      *                                                     in the native DBMS data definition.
  1103.      *
  1104.      * @return string[]
  1105.      */
  1106.     protected function getPortableNamespacesList(array $namespaces)
  1107.     {
  1108.         Deprecation::triggerIfCalledFromOutside(
  1109.             'doctrine/dbal',
  1110.             'https://github.com/doctrine/dbal/issues/4503',
  1111.             'AbstractSchemaManager::getPortableNamespacesList() is deprecated,'
  1112.                 ' use AbstractSchemaManager::listSchemaNames() instead.'
  1113.         );
  1114.         $namespacesList = [];
  1115.         foreach ($namespaces as $namespace) {
  1116.             $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
  1117.         }
  1118.         return $namespacesList;
  1119.     }
  1120.     /**
  1121.      * @param mixed $database
  1122.      *
  1123.      * @return mixed
  1124.      */
  1125.     protected function _getPortableDatabaseDefinition($database)
  1126.     {
  1127.         return $database;
  1128.     }
  1129.     /**
  1130.      * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
  1131.      *
  1132.      * @deprecated Use {@see listSchemaNames()} instead.
  1133.      *
  1134.      * @param array<string, mixed> $namespace The native DBMS namespace definition.
  1135.      *
  1136.      * @return mixed
  1137.      */
  1138.     protected function getPortableNamespaceDefinition(array $namespace)
  1139.     {
  1140.         Deprecation::triggerIfCalledFromOutside(
  1141.             'doctrine/dbal',
  1142.             'https://github.com/doctrine/dbal/issues/4503',
  1143.             'AbstractSchemaManager::getPortableNamespaceDefinition() is deprecated,'
  1144.                 ' use AbstractSchemaManager::listSchemaNames() instead.'
  1145.         );
  1146.         return $namespace;
  1147.     }
  1148.     /**
  1149.      * @param mixed[][] $sequences
  1150.      *
  1151.      * @return Sequence[]
  1152.      *
  1153.      * @throws Exception
  1154.      */
  1155.     protected function _getPortableSequencesList($sequences)
  1156.     {
  1157.         $list = [];
  1158.         foreach ($sequences as $value) {
  1159.             $list[] = $this->_getPortableSequenceDefinition($value);
  1160.         }
  1161.         return $list;
  1162.     }
  1163.     /**
  1164.      * @param mixed[] $sequence
  1165.      *
  1166.      * @return Sequence
  1167.      *
  1168.      * @throws Exception
  1169.      */
  1170.     protected function _getPortableSequenceDefinition($sequence)
  1171.     {
  1172.         throw Exception::notSupported('Sequences');
  1173.     }
  1174.     /**
  1175.      * Independent of the database the keys of the column list result are lowercased.
  1176.      *
  1177.      * The name of the created column instance however is kept in its case.
  1178.      *
  1179.      * @param string    $table        The name of the table.
  1180.      * @param string    $database
  1181.      * @param mixed[][] $tableColumns
  1182.      *
  1183.      * @return Column[]
  1184.      *
  1185.      * @throws Exception
  1186.      */
  1187.     protected function _getPortableTableColumnList($table$database$tableColumns)
  1188.     {
  1189.         $eventManager $this->_platform->getEventManager();
  1190.         $list = [];
  1191.         foreach ($tableColumns as $tableColumn) {
  1192.             $column           null;
  1193.             $defaultPrevented false;
  1194.             if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
  1195.                 $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn$table$database$this->_conn);
  1196.                 $eventManager->dispatchEvent(Events::onSchemaColumnDefinition$eventArgs);
  1197.                 $defaultPrevented $eventArgs->isDefaultPrevented();
  1198.                 $column           $eventArgs->getColumn();
  1199.             }
  1200.             if (! $defaultPrevented) {
  1201.                 $column $this->_getPortableTableColumnDefinition($tableColumn);
  1202.             }
  1203.             if ($column === null) {
  1204.                 continue;
  1205.             }
  1206.             $name        strtolower($column->getQuotedName($this->_platform));
  1207.             $list[$name] = $column;
  1208.         }
  1209.         return $list;
  1210.     }
  1211.     /**
  1212.      * Gets Table Column Definition.
  1213.      *
  1214.      * @param mixed[] $tableColumn
  1215.      *
  1216.      * @return Column
  1217.      *
  1218.      * @throws Exception
  1219.      */
  1220.     abstract protected function _getPortableTableColumnDefinition($tableColumn);
  1221.     /**
  1222.      * Aggregates and groups the index results according to the required data result.
  1223.      *
  1224.      * @param mixed[][]   $tableIndexes
  1225.      * @param string|null $tableName
  1226.      *
  1227.      * @return Index[]
  1228.      *
  1229.      * @throws Exception
  1230.      */
  1231.     protected function _getPortableTableIndexesList($tableIndexes$tableName null)
  1232.     {
  1233.         $result = [];
  1234.         foreach ($tableIndexes as $tableIndex) {
  1235.             $indexName $keyName $tableIndex['key_name'];
  1236.             if ($tableIndex['primary']) {
  1237.                 $keyName 'primary';
  1238.             }
  1239.             $keyName strtolower($keyName);
  1240.             if (! isset($result[$keyName])) {
  1241.                 $options = [
  1242.                     'lengths' => [],
  1243.                 ];
  1244.                 if (isset($tableIndex['where'])) {
  1245.                     $options['where'] = $tableIndex['where'];
  1246.                 }
  1247.                 $result[$keyName] = [
  1248.                     'name' => $indexName,
  1249.                     'columns' => [],
  1250.                     'unique' => ! $tableIndex['non_unique'],
  1251.                     'primary' => $tableIndex['primary'],
  1252.                     'flags' => $tableIndex['flags'] ?? [],
  1253.                     'options' => $options,
  1254.                 ];
  1255.             }
  1256.             $result[$keyName]['columns'][]            = $tableIndex['column_name'];
  1257.             $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
  1258.         }
  1259.         $eventManager $this->_platform->getEventManager();
  1260.         $indexes = [];
  1261.         foreach ($result as $indexKey => $data) {
  1262.             $index            null;
  1263.             $defaultPrevented false;
  1264.             if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
  1265.                 $eventArgs = new SchemaIndexDefinitionEventArgs($data$tableName$this->_conn);
  1266.                 $eventManager->dispatchEvent(Events::onSchemaIndexDefinition$eventArgs);
  1267.                 $defaultPrevented $eventArgs->isDefaultPrevented();
  1268.                 $index            $eventArgs->getIndex();
  1269.             }
  1270.             if (! $defaultPrevented) {
  1271.                 $index = new Index(
  1272.                     $data['name'],
  1273.                     $data['columns'],
  1274.                     $data['unique'],
  1275.                     $data['primary'],
  1276.                     $data['flags'],
  1277.                     $data['options']
  1278.                 );
  1279.             }
  1280.             if ($index === null) {
  1281.                 continue;
  1282.             }
  1283.             $indexes[$indexKey] = $index;
  1284.         }
  1285.         return $indexes;
  1286.     }
  1287.     /**
  1288.      * @param mixed[][] $tables
  1289.      *
  1290.      * @return string[]
  1291.      */
  1292.     protected function _getPortableTablesList($tables)
  1293.     {
  1294.         $list = [];
  1295.         foreach ($tables as $value) {
  1296.             $list[] = $this->_getPortableTableDefinition($value);
  1297.         }
  1298.         return $list;
  1299.     }
  1300.     /**
  1301.      * @param mixed $table
  1302.      *
  1303.      * @return string
  1304.      */
  1305.     protected function _getPortableTableDefinition($table)
  1306.     {
  1307.         return $table;
  1308.     }
  1309.     /**
  1310.      * @param mixed[][] $views
  1311.      *
  1312.      * @return View[]
  1313.      */
  1314.     protected function _getPortableViewsList($views)
  1315.     {
  1316.         $list = [];
  1317.         foreach ($views as $value) {
  1318.             $view $this->_getPortableViewDefinition($value);
  1319.             if ($view === false) {
  1320.                 continue;
  1321.             }
  1322.             $viewName        strtolower($view->getQuotedName($this->_platform));
  1323.             $list[$viewName] = $view;
  1324.         }
  1325.         return $list;
  1326.     }
  1327.     /**
  1328.      * @param mixed[] $view
  1329.      *
  1330.      * @return View|false
  1331.      */
  1332.     protected function _getPortableViewDefinition($view)
  1333.     {
  1334.         return false;
  1335.     }
  1336.     /**
  1337.      * @param mixed[][] $tableForeignKeys
  1338.      *
  1339.      * @return ForeignKeyConstraint[]
  1340.      */
  1341.     protected function _getPortableTableForeignKeysList($tableForeignKeys)
  1342.     {
  1343.         $list = [];
  1344.         foreach ($tableForeignKeys as $value) {
  1345.             $list[] = $this->_getPortableTableForeignKeyDefinition($value);
  1346.         }
  1347.         return $list;
  1348.     }
  1349.     /**
  1350.      * @param mixed $tableForeignKey
  1351.      *
  1352.      * @return ForeignKeyConstraint
  1353.      *
  1354.      * @abstract
  1355.      */
  1356.     protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
  1357.     {
  1358.         return $tableForeignKey;
  1359.     }
  1360.     /**
  1361.      * @param string[]|string $sql
  1362.      *
  1363.      * @return void
  1364.      *
  1365.      * @throws Exception
  1366.      */
  1367.     protected function _execSql($sql)
  1368.     {
  1369.         foreach ((array) $sql as $query) {
  1370.             $this->_conn->executeStatement($query);
  1371.         }
  1372.     }
  1373.     /**
  1374.      * Creates a schema instance for the current database.
  1375.      *
  1376.      * @return Schema
  1377.      *
  1378.      * @throws Exception
  1379.      */
  1380.     public function createSchema()
  1381.     {
  1382.         $schemaNames = [];
  1383.         if ($this->_platform->supportsSchemas()) {
  1384.             $schemaNames $this->listNamespaceNames();
  1385.         }
  1386.         $sequences = [];
  1387.         if ($this->_platform->supportsSequences()) {
  1388.             $sequences $this->listSequences();
  1389.         }
  1390.         $tables $this->listTables();
  1391.         return new Schema($tables$sequences$this->createSchemaConfig(), $schemaNames);
  1392.     }
  1393.     /**
  1394.      * Creates the configuration for this schema.
  1395.      *
  1396.      * @return SchemaConfig
  1397.      *
  1398.      * @throws Exception
  1399.      */
  1400.     public function createSchemaConfig()
  1401.     {
  1402.         $schemaConfig = new SchemaConfig();
  1403.         $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
  1404.         $searchPaths $this->getSchemaSearchPaths();
  1405.         if (isset($searchPaths[0])) {
  1406.             $schemaConfig->setName($searchPaths[0]);
  1407.         }
  1408.         $params $this->_conn->getParams();
  1409.         if (! isset($params['defaultTableOptions'])) {
  1410.             $params['defaultTableOptions'] = [];
  1411.         }
  1412.         if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
  1413.             $params['defaultTableOptions']['charset'] = $params['charset'];
  1414.         }
  1415.         $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
  1416.         return $schemaConfig;
  1417.     }
  1418.     /**
  1419.      * The search path for namespaces in the currently connected database.
  1420.      *
  1421.      * The first entry is usually the default namespace in the Schema. All
  1422.      * further namespaces contain tables/sequences which can also be addressed
  1423.      * with a short, not full-qualified name.
  1424.      *
  1425.      * For databases that don't support subschema/namespaces this method
  1426.      * returns the name of the currently connected database.
  1427.      *
  1428.      * @deprecated
  1429.      *
  1430.      * @return string[]
  1431.      *
  1432.      * @throws Exception
  1433.      */
  1434.     public function getSchemaSearchPaths()
  1435.     {
  1436.         Deprecation::triggerIfCalledFromOutside(
  1437.             'doctrine/dbal',
  1438.             'https://github.com/doctrine/dbal/pull/4821',
  1439.             'AbstractSchemaManager::getSchemaSearchPaths() is deprecated.'
  1440.         );
  1441.         $database $this->_conn->getDatabase();
  1442.         if ($database !== null) {
  1443.             return [$database];
  1444.         }
  1445.         return [];
  1446.     }
  1447.     /**
  1448.      * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
  1449.      * the type given as default.
  1450.      *
  1451.      * @internal This method should be only used from within the AbstractSchemaManager class hierarchy.
  1452.      *
  1453.      * @param string|null $comment
  1454.      * @param string      $currentType
  1455.      *
  1456.      * @return string
  1457.      */
  1458.     public function extractDoctrineTypeFromComment($comment$currentType)
  1459.     {
  1460.         if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))'$comment$match) === 1) {
  1461.             return $match[1];
  1462.         }
  1463.         return $currentType;
  1464.     }
  1465.     /**
  1466.      * @internal This method should be only used from within the AbstractSchemaManager class hierarchy.
  1467.      *
  1468.      * @param string|null $comment
  1469.      * @param string|null $type
  1470.      *
  1471.      * @return string|null
  1472.      */
  1473.     public function removeDoctrineTypeFromComment($comment$type)
  1474.     {
  1475.         if ($comment === null) {
  1476.             return null;
  1477.         }
  1478.         return str_replace('(DC2Type:' $type ')'''$comment);
  1479.     }
  1480.     /**
  1481.      * @throws Exception
  1482.      */
  1483.     private function getDatabase(string $methodName): string
  1484.     {
  1485.         $database $this->_conn->getDatabase();
  1486.         if ($database === null) {
  1487.             throw DatabaseRequired::new($methodName);
  1488.         }
  1489.         return $database;
  1490.     }
  1491.     public function createComparator(): Comparator
  1492.     {
  1493.         return new Comparator($this->_platform);
  1494.     }
  1495.     /**
  1496.      * @return array<string,list<array<string,mixed>>>
  1497.      *
  1498.      * @throws Exception
  1499.      */
  1500.     private function fetchAllAssociativeGrouped(Result $result): array
  1501.     {
  1502.         $data = [];
  1503.         foreach ($result->fetchAllAssociative() as $row) {
  1504.             $tableName          $this->_getPortableTableDefinition($row);
  1505.             $data[$tableName][] = $row;
  1506.         }
  1507.         return $data;
  1508.     }
  1509. }