Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ColumnFactory #288

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Schema\Column\AbstractColumnFactory;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

use function preg_replace;
use function strtolower;
Expand All @@ -19,10 +18,9 @@ final class ColumnFactory extends AbstractColumnFactory
* @link https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Data-Types.html
*
* @var string[]
*
* @psalm-suppress MissingClassConstType
* @psalm-var array<string, ColumnType::*>
*/
private const TYPE_MAP = [
protected const TYPE_MAP = [
'char' => ColumnType::CHAR,
'nchar' => ColumnType::CHAR,
'varchar2' => ColumnType::STRING,
Expand Down Expand Up @@ -65,21 +63,15 @@ protected function getType(string $dbType, array $info = []): string
return ColumnType::STRING;
}

return self::TYPE_MAP[$dbType] ?? ColumnType::STRING;
return parent::getType($dbType, $info);
}

public function fromType(string $type, array $info = []): ColumnSchemaInterface
protected function getColumnClass(string $type, array $info = []): string
{
if ($type === ColumnType::BINARY) {
unset($info['type']);
return new BinaryColumnSchema($type, ...$info);
return BinaryColumnSchema::class;
}

return parent::fromType($type, $info);
}

protected function isDbType(string $dbType): bool
{
return isset(self::TYPE_MAP[$dbType]);
return parent::getColumnClass($type, $info);
}
}
93 changes: 57 additions & 36 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,18 @@
/**
* Implements the Oracle Server specific schema, supporting Oracle Server 11C and above.
*
* @psalm-type ColumnInfoArray = array{
* @psalm-type ColumnArray = array{
* column_name: string,
* data_type: string,
* data_scale: string|null,
* identity_column: string,
* size: string|null,
* nullable: string,
* data_default: string|null,
* is_pk: string|null,
* identity_column: string,
* column_comment: string|null
* constraint_type: string|null,
* column_comment: string|null,
* schema: string,
* table: string
* }
*
* @psalm-type ConstraintArray = array<
Expand Down Expand Up @@ -334,6 +336,9 @@ protected function loadTableDefaultValues(string $tableName): array
*/
protected function findColumns(TableSchemaInterface $table): bool
{
$schemaName = $table->getSchemaName();
$tableName = $table->getName();

$sql = <<<SQL
SELECT
A.COLUMN_NAME,
Expand All @@ -343,30 +348,45 @@ protected function findColumns(TableSchemaInterface $table): bool
(CASE WHEN A.CHAR_LENGTH > 0 THEN A.CHAR_LENGTH ELSE A.DATA_PRECISION END) AS "size",
A.NULLABLE,
A.DATA_DEFAULT,
(
SELECT COUNT(*)
FROM ALL_CONSTRAINTS AC
INNER JOIN ALL_CONS_COLUMNS ACC ON ACC.CONSTRAINT_NAME=AC.CONSTRAINT_NAME
WHERE
AC.OWNER = A.OWNER
AND AC.TABLE_NAME = B.OBJECT_NAME
AND ACC.COLUMN_NAME = A.COLUMN_NAME
AND AC.CONSTRAINT_TYPE = 'P'
) AS IS_PK,
AC.CONSTRAINT_TYPE,
COM.COMMENTS AS COLUMN_COMMENT
FROM ALL_TAB_COLUMNS A
INNER JOIN ALL_OBJECTS B ON B.OWNER = A.OWNER AND LTRIM(B.OBJECT_NAME) = LTRIM(A.TABLE_NAME)
LEFT JOIN ALL_COL_COMMENTS COM ON (A.OWNER = COM.OWNER AND A.TABLE_NAME = COM.TABLE_NAME AND A.COLUMN_NAME = COM.COLUMN_NAME)
WHERE
A.OWNER = :schemaName
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 ALL_CONSTRAINTS AC
ON AC.OWNER = A.OWNER
AND AC.TABLE_NAME = A.TABLE_NAME
AND (AC.CONSTRAINT_TYPE = 'P'
OR AC.CONSTRAINT_TYPE = 'U'
AND (
SELECT COUNT(*)
FROM ALL_CONS_COLUMNS UCC
WHERE UCC.CONSTRAINT_NAME = AC.CONSTRAINT_NAME
AND UCC.TABLE_NAME = AC.TABLE_NAME
AND UCC.OWNER = AC.OWNER
) = 1
)
AND AC.CONSTRAINT_NAME IN (
SELECT ACC.CONSTRAINT_NAME
FROM ALL_CONS_COLUMNS ACC
WHERE ACC.OWNER = A.OWNER
AND ACC.TABLE_NAME = A.TABLE_NAME
AND ACC.COLUMN_NAME = A.COLUMN_NAME
)
WHERE A.OWNER = :schemaName
AND A.TABLE_NAME = :tableName
AND B.OBJECT_TYPE IN ('TABLE', 'VIEW', 'MATERIALIZED VIEW')
AND B.OBJECT_NAME = :tableName
ORDER BY A.COLUMN_ID
SQL;

$columns = $this->db->createCommand($sql, [
':tableName' => $table->getName(),
':schemaName' => $table->getSchemaName(),
':schemaName' => $schemaName,
':tableName' => $tableName,
])->queryAll();

if ($columns === []) {
Expand All @@ -375,9 +395,12 @@ protected function findColumns(TableSchemaInterface $table): bool

/** @psalm-var string[][] $info */
foreach ($columns as $info) {
/** @psalm-var ColumnInfoArray $info */
$info = array_change_key_case($info);

$info['schema'] = $schemaName;
$info['table'] = $tableName;

/** @psalm-var ColumnArray $info */
$column = $this->loadColumnSchema($info);

$table->column($info['column_name'], $column);
Expand Down Expand Up @@ -422,26 +445,24 @@ protected function getTableSequenceName(string $tableName): string|null
*
* @return ColumnSchemaInterface The column schema object.
*
* @psalm-param ColumnInfoArray $info The column information.
* @psalm-param ColumnArray $info The column information.
*/
private function loadColumnSchema(array $info): ColumnSchemaInterface
{
$columnFactory = $this->db->getSchema()->getColumnFactory();

$dbType = $info['data_type'];
$column = $columnFactory->fromDbType($dbType, [
$column = $this->getColumnFactory()->fromDbType($info['data_type'], [
'autoIncrement' => $info['identity_column'] === 'YES',
'comment' => $info['column_comment'],
'name' => $info['column_name'],
'notNull' => $info['nullable'] !== 'Y',
'primaryKey' => $info['constraint_type'] === 'P',
'scale' => $info['data_scale'] !== null ? (int) $info['data_scale'] : null,
'schema' => $info['schema'],
'size' => $info['size'] !== null ? (int) $info['size'] : null,
'table' => $info['table'],
'unique' => $info['constraint_type'] === 'U',
]);
/** @psalm-suppress DeprecatedMethod */
$column->name($info['column_name']);
$column->notNull($info['nullable'] !== 'Y');
$column->comment($info['column_comment']);
$column->primaryKey((bool) $info['is_pk']);
$column->autoIncrement($info['identity_column'] === 'YES');
$column->defaultValue($this->normalizeDefaultValue($info['data_default'], $column));

return $column;

return $column->defaultValue($this->normalizeDefaultValue($info['data_default'], $column));
}

/**
Expand Down
20 changes: 16 additions & 4 deletions tests/ColumnSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function testPhpTypeCast(): void
$db->close();
}

public function testColumnSchemaInstance()
public function testColumnSchemaInstance(): void
{
$db = $this->getConnection(true);
$schema = $db->getSchema();
Expand All @@ -82,18 +82,18 @@ public function testColumnSchemaInstance()
}

/** @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\ColumnSchemaProvider::predefinedTypes */
public function testPredefinedType(string $className, string $type, string $phpType)
public function testPredefinedType(string $className, string $type, string $phpType): void
{
parent::testPredefinedType($className, $type, $phpType);
}

/** @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\ColumnSchemaProvider::dbTypecastColumns */
public function testDbTypecastColumns(string $className, array $values)
public function testDbTypecastColumns(string $className, array $values): void
{
parent::testDbTypecastColumns($className, $values);
}

public function testBinaryColumnSchema()
public function testBinaryColumnSchema(): void
{
$binaryCol = new BinaryColumnSchema();
$binaryCol->dbType('BLOB');
Expand All @@ -104,4 +104,16 @@ public function testBinaryColumnSchema()
$binaryCol->dbTypecast(new Param("\x10\x11\x12", PDO::PARAM_LOB)),
);
}

public function testUniqueColumn(): void
{
$db = $this->getConnection(true);
$schema = $db->getSchema();

$this->assertTrue($schema->getTableSchema('T_constraints_1')?->getColumn('C_unique')->isUnique());
$this->assertFalse($schema->getTableSchema('T_constraints_2')?->getColumn('C_index_2_1')->isUnique());
$this->assertFalse($schema->getTableSchema('T_constraints_2')?->getColumn('C_index_2_2')->isUnique());
$this->assertTrue($schema->getTableSchema('T_upsert')?->getColumn('email')->isUnique());
$this->assertFalse($schema->getTableSchema('T_upsert')?->getColumn('recovery_email')->isUnique());
}
}
9 changes: 0 additions & 9 deletions tests/Provider/SchemaProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,6 @@ public static function columns(): array
];
}

public static function columnsTypeChar(): array
{
return [
['char_col', 'char', 100, 'CHAR'],
['char_col2', 'string', 100, 'VARCHAR2'],
['char_col3', 'string', 4000, 'VARCHAR2'],
];
}

public static function constraints(): array
{
$constraints = parent::constraints();
Expand Down
12 changes: 0 additions & 12 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,6 @@ public function testGetSchemaDefaultValues(): void
parent::testGetSchemaDefaultValues();
}

/**
* @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\SchemaProvider::columnsTypeChar
*/
public function testGetStringFieldsSize(
string $columnName,
string $columnType,
int|null $columnSize,
string $columnDbType
): void {
parent::testGetStringFieldsSize($columnName, $columnType, $columnSize, $columnDbType);
}

/**
* @throws Exception
* @throws InvalidConfigException
Expand Down
Loading