0 follower

Final Class Yiisoft\Db\Oracle\Schema

InheritanceYiisoft\Db\Oracle\Schema » Yiisoft\Db\Driver\Pdo\AbstractPdoSchema

Implements the Oracle Server specific schema, supporting Oracle Server 11C and above.

Psalm Types

Name Value
ColumnArray array{column_name: string, data_type: string, data_scale: string|null, identity_column: string, size: string|null, nullable: string, data_default: string|null, collation: string|null, constraint_type: string|null, check: string|null, column_comment: string|null, schema: string, table: string}

Protected Properties

Hide inherited properties

Property Type Description Defined By
$db \Yiisoft\Db\Connection\ConnectionInterface Yiisoft\Db\Oracle\Schema

Public Methods

Hide inherited methods

Method Description Defined By
__construct() Yiisoft\Db\Oracle\Schema

Property Details

Hide inherited properties

$db protected property
protected \Yiisoft\Db\Connection\ConnectionInterface $db null

Method Details

Hide inherited methods

__construct() public method

public __construct( \Yiisoft\Db\Connection\ConnectionInterface $db, \Yiisoft\Db\Cache\SchemaCache $schemaCache, string $defaultSchema ): mixed
$db \Yiisoft\Db\Connection\ConnectionInterface
$schemaCache \Yiisoft\Db\Cache\SchemaCache
$defaultSchema string

                public function __construct(protected ConnectionInterface $db, SchemaCache $schemaCache, string $defaultSchema)
{
    $this->defaultSchema = $defaultSchema;
    parent::__construct($db, $schemaCache);
}

            
findColumns() protected method

Collects the table column metadata.

protected findColumns( \Yiisoft\Db\Schema\TableSchemaInterface $table ): boolean
$table \Yiisoft\Db\Schema\TableSchemaInterface

The table schema.

return boolean

Whether the table exists.

                protected function findColumns(TableSchemaInterface $table): bool
{
    $schemaName = $table->getSchemaName() ?: $this->defaultSchema;
    $tableName = $table->getName();
    $sql = <<<SQL
    WITH C AS (
        SELECT AC.CONSTRAINT_TYPE, AC.SEARCH_CONDITION, ACC.COLUMN_NAME
        FROM ALL_CONSTRAINTS AC
        INNER JOIN ALL_CONS_COLUMNS ACC
            ON ACC.OWNER = AC.OWNER
            AND ACC.TABLE_NAME = AC.TABLE_NAME
            AND ACC.CONSTRAINT_NAME = AC.CONSTRAINT_NAME
        LEFT JOIN ALL_CONS_COLUMNS ACC2
            ON ACC2.OWNER = AC.OWNER
            AND ACC2.TABLE_NAME = AC.TABLE_NAME
            AND ACC2.CONSTRAINT_NAME = AC.CONSTRAINT_NAME
            AND ACC2.COLUMN_NAME != ACC.COLUMN_NAME
        WHERE AC.OWNER = :schemaName2
            AND AC.TABLE_NAME = :tableName2
            AND (AC.CONSTRAINT_TYPE = 'P'
                OR AC.CONSTRAINT_TYPE = 'U' AND ACC2.COLUMN_NAME IS NULL
                OR AC.CONSTRAINT_TYPE = 'C' AND ACC2.COLUMN_NAME IS NULL AND AC.SEARCH_CONDITION_VC != '"' || ACC.COLUMN_NAME || '" IS NOT NULL')
    )
    SELECT
        A.COLUMN_NAME,
        A.DATA_TYPE,
        A.DATA_SCALE,
        A.IDENTITY_COLUMN,
        (CASE WHEN A.CHAR_LENGTH > 0 THEN A.CHAR_LENGTH ELSE A.DATA_PRECISION END) AS "size",
        A.NULLABLE,
        A.DATA_DEFAULT,
        A.COLLATION,
        C.CONSTRAINT_TYPE,
        C2.SEARCH_CONDITION AS "check",
        COM.COMMENTS AS COLUMN_COMMENT
    FROM ALL_TAB_COLUMNS A
    INNER JOIN ALL_OBJECTS B
        ON B.OWNER = A.OWNER
        AND B.OBJECT_NAME = A.TABLE_NAME
    LEFT JOIN ALL_COL_COMMENTS COM
        ON COM.OWNER = A.OWNER
        AND COM.TABLE_NAME = A.TABLE_NAME
        AND COM.COLUMN_NAME = A.COLUMN_NAME
    LEFT JOIN C
        ON C.COLUMN_NAME = A.COLUMN_NAME
        AND C.CONSTRAINT_TYPE IN ('P', 'U')
    LEFT JOIN C C2
        ON C2.COLUMN_NAME = A.COLUMN_NAME
        AND C2.CONSTRAINT_TYPE = 'C'
    WHERE A.OWNER = :schemaName
        AND A.TABLE_NAME = :tableName
        AND B.OBJECT_TYPE IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW')
    ORDER BY A.COLUMN_ID
    SQL;
    $columns = $this->db->createCommand($sql, [
        ':schemaName' => $schemaName,
        ':schemaName2' => $schemaName,
        ':tableName' => $tableName,
        ':tableName2' => $tableName,
    ])->queryAll();
    if ($columns === []) {
        return false;
    }
    /** @psalm-var string[][] $info */
    foreach ($columns as $info) {
        $info = array_change_key_case($info);
        $info['schema'] = $schemaName;
        $info['table'] = $tableName;
        /** @psalm-var ColumnArray $info */
        $column = $this->loadColumn($info);
        $table->column($info['column_name'], $column);
    }
    return true;
}

            
findConstraints() protected method

protected findConstraints( \Yiisoft\Db\Schema\TableSchemaInterface $table ): void
$table \Yiisoft\Db\Schema\TableSchemaInterface

                protected function findConstraints(TableSchemaInterface $table): void
{
    $tableName = $this->resolveFullName($table->getName(), $table->getSchemaName());
    $table->checks(...$this->getTableMetadata($tableName, SchemaInterface::CHECKS));
    $table->foreignKeys(...$this->getTableMetadata($tableName, SchemaInterface::FOREIGN_KEYS));
    $table->indexes(...$this->getTableMetadata($tableName, SchemaInterface::INDEXES));
}

            
findSchemaNames() protected method

protected findSchemaNames( ): array

                protected function findSchemaNames(): array
{
    $sql = <<<SQL
    SELECT "u"."USERNAME"
    FROM "DBA_USERS" "u"
    WHERE "u"."DEFAULT_TABLESPACE" NOT IN ('SYSTEM', 'SYSAUX')
    ORDER BY "u"."USERNAME" ASC
    SQL;
    /** @var string[] */
    return $this->db->createCommand($sql)->queryColumn();
}

            
findTableComment() protected method

protected findTableComment( \Yiisoft\Db\Schema\TableSchemaInterface $tableSchema ): void
$tableSchema \Yiisoft\Db\Schema\TableSchemaInterface

                protected function findTableComment(TableSchemaInterface $tableSchema): void
{
    $sql = <<<SQL
    SELECT "COMMENTS"
    FROM ALL_TAB_COMMENTS
    WHERE
          "OWNER" = :schemaName AND
          "TABLE_NAME" = :tableName
    SQL;
    $comment = $this->db->createCommand($sql, [
        ':schemaName' => $tableSchema->getSchemaName() ?: $this->defaultSchema,
        ':tableName' => $tableSchema->getName(),
    ])->queryScalar();
    $tableSchema->comment(is_string($comment) ? $comment : null);
}

            
findTableNames() protected method

protected findTableNames( string $schema '' ): array
$schema string

                protected function findTableNames(string $schema = ''): array
{
    if ($schema === '') {
        $sql = <<<SQL
        SELECT TABLE_NAME
        FROM USER_TABLES
        UNION ALL
        SELECT VIEW_NAME AS TABLE_NAME
        FROM USER_VIEWS
        UNION ALL
        SELECT MVIEW_NAME AS TABLE_NAME
        FROM USER_MVIEWS
        ORDER BY TABLE_NAME
        SQL;
        $command = $this->db->createCommand($sql);
    } else {
        $sql = <<<SQL
        SELECT OBJECT_NAME
        FROM ALL_OBJECTS
        WHERE OBJECT_TYPE IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW') AND OWNER = :schema
        ORDER BY OBJECT_NAME
        SQL;
        $command = $this->db->createCommand($sql, [':schema' => $schema]);
    }
    /** @var string[] */
    return $command->queryColumn();
}

            
findViewNames() protected method

protected findViewNames( string $schema '' ): array
$schema string

                protected function findViewNames(string $schema = ''): array
{
    $sql = match ($schema) {
        '' => 'SELECT VIEW_NAME FROM USER_VIEWS',
        default => "SELECT VIEW_NAME FROM ALL_VIEWS WHERE OWNER = '$schema'",
    };
    /** @var string[] */
    return $this->db->createCommand($sql)->queryColumn();
}

            
loadResultColumn() protected method

protected loadResultColumn( array{"oci:decl_type": integer|string, native_type: string, pdo_type: integer, scale: integer, table?: string, flags: string[], name: string, len: integer, precision: integer} $metadata ): \Yiisoft\Db\Schema\Column\ColumnInterface|null
$metadata array{"oci:decl_type": integer|string, native_type: string, pdo_type: integer, scale: integer, table?: string, flags: string[], name: string, len: integer, precision: integer}

                protected function loadResultColumn(array $metadata): ?ColumnInterface
{
    if (empty($metadata['oci:decl_type'])) {
        return null;
    }
    $dbType = match ($metadata['oci:decl_type']) {
        119 => 'json',
        'TIMESTAMP WITH TIMEZONE' => 'timestamp with time zone',
        'TIMESTAMP WITH LOCAL TIMEZONE' => 'timestamp with local time zone',
        default => strtolower((string) $metadata['oci:decl_type']),
    };
    $columnInfo = ['source' => ColumnInfoSource::QUERY_RESULT];
    if (!empty($metadata['table'])) {
        $columnInfo['table'] = $metadata['table'];
        $columnInfo['name'] = $metadata['name'];
    } elseif (!empty($metadata['name'])) {
        $columnInfo['name'] = $metadata['name'];
    }
    if ($metadata['pdo_type'] === 3) {
        $columnInfo['type'] = ColumnType::BINARY;
    }
    if (!empty($metadata['precision'])) {
        $columnInfo['size'] = $metadata['precision'];
    }
    /** @psalm-suppress PossiblyUndefinedArrayOffset, InvalidArrayOffset */
    match ($dbType) {
        'timestamp',
        'timestamp with time zone',
        'timestamp with local time zone' => $columnInfo['size'] = $metadata['scale'],
        'interval day to second',
        'interval year to month'
            => [$columnInfo['size'], $columnInfo['scale']] = [$metadata['scale'], $metadata['precision']],
        'number' => $metadata['scale'] !== -127 ? $columnInfo['scale'] = $metadata['scale'] : null,
        'float' => null,
        default => $columnInfo['size'] = $metadata['len'],
    };
    if ($dbType === 'timestamp with local time zone') {
        $columnInfo['dbTimezone'] = $this->db->getServerInfo()->getTimezone();
    }
    $columnInfo['notNull'] = in_array('not_null', $metadata['flags'], true);
    /** @psalm-suppress MixedArgumentTypeCoercion */
    return $this->db->getColumnFactory()->fromDbType($dbType, $columnInfo);
}

            
loadTableChecks() protected method

protected loadTableChecks( string $tableName ): array
$tableName string

                protected function loadTableChecks(string $tableName): array
{
    /** @var Check[] */
    return $this->loadTableConstraints($tableName, self::CHECKS);
}

            
loadTableDefaultValues() protected method

protected loadTableDefaultValues( string $tableName ): array
$tableName string
throws \Yiisoft\Db\Exception\NotSupportedException

If this method is called.

                protected function loadTableDefaultValues(string $tableName): array
{
    throw new NotSupportedException(__METHOD__ . ' is not supported by Oracle.');
}

            
loadTableForeignKeys() protected method

protected loadTableForeignKeys( string $tableName ): array
$tableName string

                protected function loadTableForeignKeys(string $tableName): array
{
    /** @var ForeignKey[] */
    return $this->loadTableConstraints($tableName, self::FOREIGN_KEYS);
}

            
loadTableIndexes() protected method

protected loadTableIndexes( string $tableName ): array
$tableName string

                protected function loadTableIndexes(string $tableName): array
{
    $sql = <<<SQL
    SELECT "ui"."INDEX_NAME" AS "name", "uicol"."COLUMN_NAME" AS "column_name",
    CASE "ui"."UNIQUENESS" WHEN 'UNIQUE' THEN 1 ELSE 0 END AS "is_unique",
    CASE WHEN "uc"."CONSTRAINT_NAME" IS NOT NULL THEN 1 ELSE 0 END AS "is_primary_key"
    FROM "SYS"."USER_INDEXES" "ui"
    LEFT JOIN "SYS"."USER_IND_COLUMNS" "uicol"
    ON "uicol"."INDEX_NAME" = "ui"."INDEX_NAME"
    LEFT JOIN "SYS"."USER_CONSTRAINTS" "uc"
    ON "uc"."OWNER" = "ui"."TABLE_OWNER" AND "uc"."CONSTRAINT_NAME" = "ui"."INDEX_NAME" AND "uc"."CONSTRAINT_TYPE" = 'P'
    WHERE "ui"."TABLE_OWNER" = :schemaName AND "ui"."TABLE_NAME" = :tableName
    ORDER BY "uicol"."COLUMN_POSITION" ASC
    SQL;
    $nameParts = $this->db->getQuoter()->getTableNameParts($tableName);
    $indexes = $this->db->createCommand($sql, [
        ':schemaName' => $nameParts['schemaName'] ?? $this->defaultSchema,
        ':tableName' => $nameParts['name'],
    ])->queryAll();
    /** @psalm-var list<array<string,mixed>> $indexes */
    $indexes = array_map(array_change_key_case(...), $indexes);
    $indexes = DbArrayHelper::arrange($indexes, ['name']);
    $result = [];
    /**
     * @var string $name
     * @var array[] $index
     */
    foreach ($indexes as $name => $index) {
        $columnNames = array_column($index, 'column_name');
        if ($columnNames === [null]) {
            $columnNames = [];
        }
        /** @var list<string> $columnNames */
        $result[$name] = new Index(
            $name,
            $columnNames,
            (bool) $index[0]['is_unique'],
            (bool) $index[0]['is_primary_key'],
        );
    }
    return $result;
}

            
loadTableSchema() protected method

protected loadTableSchema( string $name ): \Yiisoft\Db\Schema\TableSchemaInterface|null
$name string

                protected function loadTableSchema(string $name): ?TableSchemaInterface
{
    $table = new TableSchema(...$this->db->getQuoter()->getTableNameParts($name));
    if ($this->findColumns($table)) {
        $this->findTableComment($table);
        $this->findConstraints($table);
        $table->sequenceName($this->getTableSequenceName($table->getName()));
        return $table;
    }
    return null;
}