Skip to content

Commit

Permalink
Fix ColumnDefinitionParser
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jan 18, 2025
1 parent 3f867e3 commit 58dfcbc
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/Column/ColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -26,7 +29,7 @@ final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder
'number',
'float',
'timestamp',
'interval day(0) to second',
'interval day to second',
'raw',
'urowid',
];
Expand All @@ -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)) {
Expand Down
47 changes: 47 additions & 0 deletions src/Column/ColumnDefinitionParser.php
Original file line number Diff line number Diff line change
@@ -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);
}
}
5 changes: 5 additions & 0 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
27 changes: 27 additions & 0 deletions tests/ColumnDefinitionParserTest.php
Original file line number Diff line number Diff line change
@@ -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);
}
}
22 changes: 22 additions & 0 deletions tests/Provider/ColumnDefinitionParserProvider.php
Original file line number Diff line number Diff line change
@@ -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']],
];
}
}

0 comments on commit 58dfcbc

Please sign in to comment.