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

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