Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Doctrine\DBAL\Schema;use Doctrine\DBAL\Exception;use Doctrine\DBAL\Platforms\DB2Platform;use Doctrine\DBAL\Result;use Doctrine\DBAL\Types\Type;use Doctrine\DBAL\Types\Types;use Doctrine\Deprecations\Deprecation;use function array_change_key_case;use function implode;use function preg_match;use function str_replace;use function strpos;use function strtolower;use function strtoupper;use function substr;use const CASE_LOWER;/*** IBM Db2 Schema Manager.** @extends AbstractSchemaManager<DB2Platform>*/class DB2SchemaManager extends AbstractSchemaManager{/*** {@inheritDoc}*/public function listTableNames(){return $this->doListTableNames();}/*** {@inheritDoc}*/public function listTables(){return $this->doListTables();}/*** {@inheritDoc}** @deprecated Use {@see introspectTable()} instead.*/public function listTableDetails($name){Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/5595','%s is deprecated. Use introspectTable() instead.',__METHOD__,);return $this->doListTableDetails($name);}/*** {@inheritDoc}*/public function listTableColumns($table, $database = null){return $this->doListTableColumns($table, $database);}/*** {@inheritDoc}*/public function listTableIndexes($table){return $this->doListTableIndexes($table);}/*** {@inheritDoc}*/public function listTableForeignKeys($table, $database = null){return $this->doListTableForeignKeys($table, $database);}/*** {@inheritdoc}** @throws Exception*/protected function _getPortableTableColumnDefinition($tableColumn){$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);$length = null;$fixed = null;$scale = false;$precision = false;$default = null;if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') {$default = $tableColumn['default'];if (preg_match('/^\'(.*)\'$/s', $default, $matches) === 1) {$default = str_replace("''", "'", $matches[1]);}}$type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);if (isset($tableColumn['comment'])) {$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);}switch (strtolower($tableColumn['typename'])) {case 'varchar':if ($tableColumn['codepage'] === 0) {$type = Types::BINARY;}$length = $tableColumn['length'];$fixed = false;break;case 'character':if ($tableColumn['codepage'] === 0) {$type = Types::BINARY;}$length = $tableColumn['length'];$fixed = true;break;case 'clob':$length = $tableColumn['length'];break;case 'decimal':case 'double':case 'real':$scale = $tableColumn['scale'];$precision = $tableColumn['length'];break;}$options = ['length' => $length,'unsigned' => false,'fixed' => (bool) $fixed,'default' => $default,'autoincrement' => (bool) $tableColumn['autoincrement'],'notnull' => $tableColumn['nulls'] === 'N','scale' => null,'precision' => null,'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''? $tableColumn['comment']: null,'platformOptions' => [],];if ($scale !== null && $precision !== null) {$options['scale'] = $scale;$options['precision'] = $precision;}return new Column($tableColumn['colname'], Type::getType($type), $options);}/*** {@inheritdoc}*/protected function _getPortableTableDefinition($table){$table = array_change_key_case($table, CASE_LOWER);return $table['name'];}/*** {@inheritdoc}*/protected function _getPortableTableIndexesList($tableIndexes, $tableName = null){foreach ($tableIndexes as &$tableIndexRow) {$tableIndexRow = array_change_key_case($tableIndexRow, CASE_LOWER);$tableIndexRow['primary'] = (bool) $tableIndexRow['primary'];}return parent::_getPortableTableIndexesList($tableIndexes, $tableName);}/*** {@inheritdoc}*/protected function _getPortableTableForeignKeyDefinition($tableForeignKey){return new ForeignKeyConstraint($tableForeignKey['local_columns'],$tableForeignKey['foreign_table'],$tableForeignKey['foreign_columns'],$tableForeignKey['name'],$tableForeignKey['options'],);}/*** {@inheritdoc}*/protected function _getPortableTableForeignKeysList($tableForeignKeys){$foreignKeys = [];foreach ($tableForeignKeys as $tableForeignKey) {$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);if (! isset($foreignKeys[$tableForeignKey['index_name']])) {$foreignKeys[$tableForeignKey['index_name']] = ['local_columns' => [$tableForeignKey['local_column']],'foreign_table' => $tableForeignKey['foreign_table'],'foreign_columns' => [$tableForeignKey['foreign_column']],'name' => $tableForeignKey['index_name'],'options' => ['onUpdate' => $tableForeignKey['on_update'],'onDelete' => $tableForeignKey['on_delete'],],];} else {$foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column'];$foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column'];}}return parent::_getPortableTableForeignKeysList($foreignKeys);}/*** @param string $def** @return string|null*/protected function _getPortableForeignKeyRuleDef($def){if ($def === 'C') {return 'CASCADE';}if ($def === 'N') {return 'SET NULL';}return null;}/*** {@inheritdoc}*/protected function _getPortableViewDefinition($view){$view = array_change_key_case($view, CASE_LOWER);$sql = '';$pos = strpos($view['text'], ' AS ');if ($pos !== false) {$sql = substr($view['text'], $pos + 4);}return new View($view['name'], $sql);}protected function normalizeName(string $name): string{$identifier = new Identifier($name);return $identifier->isQuoted() ? $identifier->getName() : strtoupper($name);}protected function selectTableNames(string $databaseName): Result{$sql = <<<'SQL'SELECT NAMEFROM SYSIBM.SYSTABLESWHERE TYPE = 'T'AND CREATOR = ?SQL;return $this->_conn->executeQuery($sql, [$databaseName]);}protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result{$sql = 'SELECT';if ($tableName === null) {$sql .= ' C.TABNAME AS NAME,';}$sql .= <<<'SQL'C.COLNAME,C.TYPENAME,C.CODEPAGE,C.NULLS,C.LENGTH,C.SCALE,C.REMARKS AS COMMENT,CASEWHEN C.GENERATED = 'D' THEN 1ELSE 0END AS AUTOINCREMENT,C.DEFAULTFROM SYSCAT.COLUMNS CJOIN SYSCAT.TABLES AS TON T.TABSCHEMA = C.TABSCHEMAAND T.TABNAME = C.TABNAMESQL;$conditions = ['C.TABSCHEMA = ?', "T.TYPE = 'T'"];$params = [$databaseName];if ($tableName !== null) {$conditions[] = 'C.TABNAME = ?';$params[] = $tableName;}$sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY C.TABNAME, C.COLNO';return $this->_conn->executeQuery($sql, $params);}protected function selectIndexColumns(string $databaseName, ?string $tableName = null): Result{$sql = 'SELECT';if ($tableName === null) {$sql .= ' IDX.TABNAME AS NAME,';}$sql .= <<<'SQL'IDX.INDNAME AS KEY_NAME,IDXCOL.COLNAME AS COLUMN_NAME,CASEWHEN IDX.UNIQUERULE = 'P' THEN 1ELSE 0END AS PRIMARY,CASEWHEN IDX.UNIQUERULE = 'D' THEN 1ELSE 0END AS NON_UNIQUEFROM SYSCAT.INDEXES AS IDXJOIN SYSCAT.TABLES AS TON IDX.TABSCHEMA = T.TABSCHEMA AND IDX.TABNAME = T.TABNAMEJOIN SYSCAT.INDEXCOLUSE AS IDXCOLON IDX.INDSCHEMA = IDXCOL.INDSCHEMA AND IDX.INDNAME = IDXCOL.INDNAMESQL;$conditions = ['IDX.TABSCHEMA = ?', "T.TYPE = 'T'"];$params = [$databaseName];if ($tableName !== null) {$conditions[] = 'IDX.TABNAME = ?';$params[] = $tableName;}$sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY IDX.INDNAME, IDXCOL.COLSEQ';return $this->_conn->executeQuery($sql, $params);}protected function selectForeignKeyColumns(string $databaseName, ?string $tableName = null): Result{$sql = 'SELECT';if ($tableName === null) {$sql .= ' R.TABNAME AS NAME,';}$sql .= <<<'SQL'FKCOL.COLNAME AS LOCAL_COLUMN,R.REFTABNAME AS FOREIGN_TABLE,PKCOL.COLNAME AS FOREIGN_COLUMN,R.CONSTNAME AS INDEX_NAME,CASEWHEN R.UPDATERULE = 'R' THEN 'RESTRICT'END AS ON_UPDATE,CASEWHEN R.DELETERULE = 'C' THEN 'CASCADE'WHEN R.DELETERULE = 'N' THEN 'SET NULL'WHEN R.DELETERULE = 'R' THEN 'RESTRICT'END AS ON_DELETEFROM SYSCAT.REFERENCES AS RJOIN SYSCAT.TABLES AS TON T.TABSCHEMA = R.TABSCHEMAAND T.TABNAME = R.TABNAMEJOIN SYSCAT.KEYCOLUSE AS FKCOLON FKCOL.CONSTNAME = R.CONSTNAMEAND FKCOL.TABSCHEMA = R.TABSCHEMAAND FKCOL.TABNAME = R.TABNAMEJOIN SYSCAT.KEYCOLUSE AS PKCOLON PKCOL.CONSTNAME = R.REFKEYNAMEAND PKCOL.TABSCHEMA = R.REFTABSCHEMAAND PKCOL.TABNAME = R.REFTABNAMEAND PKCOL.COLSEQ = FKCOL.COLSEQSQL;$conditions = ['R.TABSCHEMA = ?', "T.TYPE = 'T'"];$params = [$databaseName];if ($tableName !== null) {$conditions[] = 'R.TABNAME = ?';$params[] = $tableName;}$sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY R.CONSTNAME, FKCOL.COLSEQ';return $this->_conn->executeQuery($sql, $params);}/*** {@inheritDoc}*/protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array{$sql = 'SELECT NAME, REMARKS';$conditions = [];$params = [];if ($tableName !== null) {$conditions[] = 'NAME = ?';$params[] = $tableName;}$sql .= ' FROM SYSIBM.SYSTABLES';if ($conditions !== []) {$sql .= ' WHERE ' . implode(' AND ', $conditions);}/** @var array<string,array<string,mixed>> $metadata */$metadata = $this->_conn->executeQuery($sql, $params)->fetchAllAssociativeIndexed();$tableOptions = [];foreach ($metadata as $table => $data) {$data = array_change_key_case($data, CASE_LOWER);$tableOptions[$table] = ['comment' => $data['remarks']];}return $tableOptions;}}