Skip to content

Commit

Permalink
Improve and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jan 19, 2025
1 parent a50f60f commit 0c1c2d9
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 41 deletions.
68 changes: 36 additions & 32 deletions src/Column/ColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,47 +67,51 @@ protected function buildOnUpdate(string $onUpdate): string

protected function getDbType(ColumnInterface $column): string
{
$dbType = $column->getDbType();
$size = $column->getSize();
$scale = $column->getScale();

/** @psalm-suppress DocblockTypeContradiction */
return $column->getDbType() ?? match ($column->getType()) {
ColumnType::BOOLEAN => 'number(1)',
ColumnType::BIT => match (true) {
$size === null => 'number(38)',
$size <= 126 => 'number(' . ceil(log10(2 ** $size)) . ')',
default => 'raw(' . ceil($size / 8) . ')',
return match ($dbType) {
default => $dbType,
null => match ($column->getType()) {
ColumnType::BOOLEAN => 'number(1)',
ColumnType::BIT => match (true) {
$size === null => 'number(38)',
$size <= 126 => 'number(' . ceil(log10(2 ** $size)) . ')',
default => 'raw(' . ceil($size / 8) . ')',
},
ColumnType::TINYINT => 'number(' . ($size ?? 3) . ')',
ColumnType::SMALLINT => 'number(' . ($size ?? 5) . ')',
ColumnType::INTEGER => 'number(' . ($size ?? 10) . ')',
ColumnType::BIGINT => 'number(' . ($size ?? 20) . ')',
ColumnType::FLOAT => 'binary_float',
ColumnType::DOUBLE => 'binary_double',
ColumnType::DECIMAL => 'number(' . ($size ?? 10) . ',' . ($scale ?? 0) . ')',
ColumnType::MONEY => 'number(' . ($size ?? 19) . ',' . ($scale ?? 4) . ')',
ColumnType::CHAR => 'char',
ColumnType::STRING => 'varchar2(' . ($size ?? 255) . ')',
ColumnType::TEXT => 'clob',
ColumnType::BINARY => 'blob',
ColumnType::UUID => 'raw(16)',
ColumnType::DATETIME => 'timestamp',
ColumnType::TIMESTAMP => 'timestamp',
ColumnType::DATE => 'date',
ColumnType::TIME => 'interval day(0) to second' . ($size !== null ? "($size)" : ''),
ColumnType::ARRAY => 'clob',
ColumnType::STRUCTURED => 'clob',
ColumnType::JSON => 'clob',
default => 'varchar2',
},
ColumnType::TINYINT => 'number(' . ($size ?? 3) . ')',
ColumnType::SMALLINT => 'number(' . ($size ?? 5) . ')',
ColumnType::INTEGER => 'number(' . ($size ?? 10) . ')',
ColumnType::BIGINT => 'number(' . ($size ?? 20) . ')',
ColumnType::FLOAT => 'binary_float',
ColumnType::DOUBLE => 'binary_double',
ColumnType::DECIMAL => 'number(' . ($size ?? 10) . ',' . ($column->getScale() ?? 0) . ')',
ColumnType::MONEY => 'number(' . ($size ?? 19) . ',' . ($column->getScale() ?? 4) . ')',
ColumnType::CHAR => 'char',
ColumnType::STRING => 'varchar2(' . ($size ?? 255) . ')',
ColumnType::TEXT => 'clob',
ColumnType::BINARY => 'blob',
ColumnType::UUID => 'raw(16)',
ColumnType::DATETIME => 'timestamp',
ColumnType::TIMESTAMP => 'timestamp',
ColumnType::DATE => 'date',
ColumnType::TIME => 'interval day(0) to second',
ColumnType::ARRAY => 'clob',
ColumnType::STRUCTURED => 'clob',
ColumnType::JSON => 'clob',
default => 'varchar2',
'timestamp with time zone' => 'timestamp' . ($size !== null ? "($size)" : '') . ' with time zone',
'timestamp with local time zone' => 'timestamp' . ($size !== null ? "($size)" : '') . ' with local time zone',
'interval day to second' => 'interval day' . ($scale !== null ? "($scale)" : '') . ' to second' . ($size !== null ? "($size)" : ''),
'interval year to month' => 'interval year' . ($scale !== null ? "($scale)" : '') . ' to month',
};
}

protected function getDefaultUuidExpression(): string
{
return 'sys_guid()';
}

protected function isAllowSize(string $dbType): bool
{
return in_array(strtolower(preg_replace('/\([^)]+\)/', '', $dbType)), self::TYPES_WITH_SIZE, true);
}
}
16 changes: 12 additions & 4 deletions src/Column/ColumnDefinitionParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\Oracle\Column;

use function preg_match;
use function preg_replace;
use function strlen;
use function strtolower;
use function substr;
Expand All @@ -16,9 +17,10 @@ final class ColumnDefinitionParser extends \Yiisoft\Db\Syntax\ColumnDefinitionPa
{
private const TYPE_PATTERN = '/^('
. 'timestamp\s*(?:\((\d+)\))? with(?: local)? time zone'
. '|interval year\s*(?:\(\d+\))? to month'
. '|interval year\s*(?:\((\d+)\))? to month'
. ')|('
. 'interval day\s*(?:\(\d+\))? to second'
. 'interval day\s*(?:\((\d+)\))? to second'
. '|long raw'
. '|\w*'
. ')\s*(?:\(([^)]+)\))?\s*'
. '/i';
Expand All @@ -27,10 +29,10 @@ public function parse(string $definition): array
{
preg_match(self::TYPE_PATTERN, $definition, $matches);

$type = strtolower($matches[3] ?? $matches[1]);
$type = strtolower(preg_replace('/\s*\(\d+\)/', '', $matches[4] ?? $matches[1]));
$info = ['type' => $type];

$typeDetails = $matches[4] ?? $matches[2] ?? '';
$typeDetails = $matches[6] ?? $matches[2] ?? '';

if ($typeDetails !== '') {
if ($type === 'enum') {
Expand All @@ -40,6 +42,12 @@ public function parse(string $definition): array
}
}

$scale = $matches[5] ?? $matches[3] ?? '';

if ($scale !== '') {
$info += ['scale' => (int) $scale];
}

$extra = substr($definition, strlen($matches[0]));

return $info + $this->extraInfo($extra);
Expand Down
15 changes: 13 additions & 2 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Yiisoft\Db\Schema\Column\AbstractColumnFactory;
use Yiisoft\Db\Schema\Column\ColumnInterface;

use function in_array;
use function preg_replace;
use function rtrim;
use function strtolower;
Expand Down Expand Up @@ -68,8 +69,18 @@ protected function getType(string $dbType, array $info = []): string

$dbType = preg_replace('/\([^)]+\)/', '', $dbType);

if ($dbType === 'interval day to second' && isset($info['size']) && $info['size'] > 0) {
return ColumnType::STRING;
if (in_array($dbType, [
'timestamp',
'timestamp with time zone',
'timestamp with local time zone',
'interval day to second',
'interval year to month',
], true)) {
[$info['size'], $info['scale']] = [$info['scale'] ?? null, $info['size'] ?? null];

if ($dbType === 'interval day to second' && $info['scale'] > 0) {
return ColumnType::STRING;
}
}

return parent::getType($dbType, $info);
Expand Down
8 changes: 5 additions & 3 deletions tests/Provider/ColumnDefinitionParserProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ public static function parse(): array
{
return [
...parent::parse(),
['long raw', ['type' => 'long raw']],
['interval day to second', ['type' => 'interval day to second']],
['interval day to second (2)', ['type' => 'interval day to second', 'size' => 2]],
['interval day(0) to second(2)', ['type' => 'interval day(0) to second', 'size' => 2]],
['interval day(0) to second(2)', ['type' => 'interval day to second', 'size' => 2, 'scale' => 0]],
['timestamp with time zone', ['type' => 'timestamp with time zone']],
['timestamp (3) with time zone', ['type' => 'timestamp (3) with time zone', 'size' => 3]],
['timestamp(3) with local time zone', ['type' => 'timestamp(3) with local time zone', 'size' => 3]],
['timestamp (3) with time zone', ['type' => 'timestamp with time zone', 'size' => 3]],
['timestamp(3) with local time zone', ['type' => 'timestamp with local time zone', 'size' => 3]],
['interval year to month', ['type' => 'interval year to month']],
['interval year (3) to month', ['type' => 'interval year to month', 'scale' => 3]],
];
}
}
4 changes: 4 additions & 0 deletions tests/Provider/QueryBuilderProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ public static function buildColumnDefinition(): array

['number(10) REFERENCES "ref_table" ("id")', ColumnBuilder::integer()->reference($referenceRestrict)],
['number(10) REFERENCES "ref_table" ("id") ON DELETE SET NULL', ColumnBuilder::integer()->reference($referenceSetNull)],
['timestamp(3) with time zone', 'timestamp (3) with time zone'],
['timestamp with local time zone', 'timestamp with local time zone'],
['interval day(5) to second(6)', 'interval day(5) to second (6)'],
['interval year(8) to month', 'interval year(8) to month'],
];
}

Expand Down

0 comments on commit 0c1c2d9

Please sign in to comment.