diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php index 43acc39..ac2cd3f 100644 --- a/src/Column/ColumnDefinitionBuilder.php +++ b/src/Column/ColumnDefinitionBuilder.php @@ -9,7 +9,10 @@ use Yiisoft\Db\Schema\Column\ColumnInterface; use function ceil; +use function in_array; use function log10; +use function preg_replace; +use function strtolower; use function strtoupper; final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder @@ -26,7 +29,7 @@ final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder 'number', 'float', 'timestamp', - 'interval day(0) to second', + 'interval day to second', 'raw', 'urowid', ]; @@ -48,6 +51,11 @@ public function build(ColumnInterface $column): string . $this->buildExtra($column); } + protected function isAllowSize(string $dbType): bool + { + return in_array(strtolower(preg_replace('/\([^)]+\)/', '', $dbType)), self::TYPES_WITH_SIZE, true); + } + protected function buildOnDelete(string $onDelete): string { return match ($onDelete = strtoupper($onDelete)) { diff --git a/src/Column/ColumnDefinitionParser.php b/src/Column/ColumnDefinitionParser.php new file mode 100644 index 0000000..ebb1357 --- /dev/null +++ b/src/Column/ColumnDefinitionParser.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +namespace Yiisoft\Db\Oracle\Column; + +use function preg_match; +use function strlen; +use function strtolower; +use function substr; + +/** + * Parses column definition string. For example, `string(255)` or `int unsigned`. + */ +final class ColumnDefinitionParser extends \Yiisoft\Db\Syntax\ColumnDefinitionParser +{ + private const TYPE_PATTERN = '/^(' + . 'timestamp\s*(?:\((\d+)\))? with(?: local)? time zone' + . '|interval year\s*(?:\(\d+\))? to month' + . ')|(' + . 'interval day\s*(?:\(\d+\))? to second' + . '|\w*' + . ')\s*(?:\(([^)]+)\))?\s*' + . '/i'; + + public function parse(string $definition): array + { + preg_match(self::TYPE_PATTERN, $definition, $matches); + + $type = strtolower($matches[3] ?? $matches[1]); + $info = ['type' => $type]; + + $typeDetails = $matches[4] ?? $matches[2] ?? ''; + + if ($typeDetails !== '') { + if ($type === 'enum') { + $info += $this->enumInfo($typeDetails); + } else { + $info += $this->sizeInfo($typeDetails); + } + } + + $extra = substr($definition, strlen($matches[0])); + + return $info + $this->extraInfo($extra); + } +} diff --git a/src/Column/ColumnFactory.php b/src/Column/ColumnFactory.php index b2fa346..a9a40f3 100644 --- a/src/Column/ColumnFactory.php +++ b/src/Column/ColumnFactory.php @@ -49,6 +49,11 @@ final class ColumnFactory extends AbstractColumnFactory 'long' => ColumnType::TEXT, ]; + protected function columnDefinitionParser(): ColumnDefinitionParser + { + return new ColumnDefinitionParser(); + } + protected function getType(string $dbType, array $info = []): string { $dbType = strtolower($dbType); diff --git a/tests/ColumnDefinitionParserTest.php b/tests/ColumnDefinitionParserTest.php new file mode 100644 index 0000000..de74477 --- /dev/null +++ b/tests/ColumnDefinitionParserTest.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +namespace Yiisoft\Db\Oracle\Tests; + +use Yiisoft\Db\Oracle\Column\ColumnDefinitionParser; +use Yiisoft\Db\Tests\AbstractColumnDefinitionParserTest; + +/** + * @group oracle + */ +final class ColumnDefinitionParserTest extends AbstractColumnDefinitionParserTest +{ + protected function createColumnDefinitionParser(): ColumnDefinitionParser + { + return new ColumnDefinitionParser(); + } + + /** + * @dataProvider \Yiisoft\Db\Oracle\Tests\Provider\ColumnDefinitionParserProvider::parse + */ + public function testParse(string $definition, array $expected): void + { + parent::testParse($definition, $expected); + } +} diff --git a/tests/Provider/ColumnDefinitionParserProvider.php b/tests/Provider/ColumnDefinitionParserProvider.php new file mode 100644 index 0000000..e72e5ac --- /dev/null +++ b/tests/Provider/ColumnDefinitionParserProvider.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace Yiisoft\Db\Oracle\Tests\Provider; + +class ColumnDefinitionParserProvider extends \Yiisoft\Db\Tests\Provider\ColumnDefinitionParserProvider +{ + public static function parse(): array + { + return [ + ...parent::parse(), + ['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]], + ['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]], + ['interval year to month', ['type' => 'interval year to month']], + ]; + } +}