Skip to content

Commit ba043b6

Browse files
authored
Improve ColumnDefinitionParser::extraInfo() method (#900)
1 parent 3167625 commit ba043b6

5 files changed

Lines changed: 62 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
- New #864, #897, #898: Realize column factory (@Tigrov)
3939
- Enh #875: Ignore "Packets out of order..." warnings in `AbstractPdoCommand::internalExecute()` method (@Tigrov)
4040
- Enh #877: Separate column type constants (@Tigrov)
41-
- Enh #878: Realize `ColumnBuilder` class (@Tigrov)
41+
- New #878: Realize `ColumnBuilder` class (@Tigrov)
42+
- New #878, #900: Realize `ColumnDefinitionParser` class (@Tigrov)
4243
- Enh #881: Refactor `ColumnSchemaInterface` and `AbstractColumnSchema` (@Tigrov)
4344
- New #882: Move `ArrayColumnSchema` and `StructuredColumnSchema` classes from `db-pgsql` package (@Tigrov)
4445
- New #883, #901: Add `ColumnDefinitionBuilder` class and `QueryBuilderInterface::buildColumnDefinition()` method (@Tigrov)

src/Syntax/ColumnDefinitionParser.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
use function explode;
88
use function preg_match;
99
use function preg_match_all;
10-
use function str_ireplace;
11-
use function stripos;
10+
use function str_replace;
1211
use function strlen;
1312
use function strtolower;
1413
use function substr;
@@ -27,11 +26,15 @@ final class ColumnDefinitionParser
2726
* @return array The column information.
2827
*
2928
* @psalm-return array{
29+
* check?: string,
30+
* defaultValueRaw?: string,
3031
* enumValues?: list<string>,
3132
* extra?: string,
33+
* notNull?: bool,
3234
* scale?: int,
3335
* size?: int,
3436
* type: lowercase-string,
37+
* unique?: bool,
3538
* unsigned?: bool,
3639
* }
3740
*/
@@ -66,7 +69,14 @@ private function enumInfo(string $values): array
6669
}
6770

6871
/**
69-
* @psalm-return array{unsigned?: bool, extra?: string}
72+
* @psalm-return array{
73+
* check?: string,
74+
* defaultValueRaw?: string,
75+
* extra?: string,
76+
* notNull?: bool,
77+
* unique?: bool,
78+
* unsigned?: bool
79+
* }
7080
*/
7181
private function extraInfo(string $extra): array
7282
{
@@ -75,12 +85,41 @@ private function extraInfo(string $extra): array
7585
}
7686

7787
$info = [];
88+
$bracketsPattern = '(\(((?>[^()]+)|(?-2))*\))';
89+
$defaultPattern = "/\\s*\\bDEFAULT\\s+('(?:[^']|'')*'|\"(?:[^\"]|\"\")*\"|[^(\\s]*$bracketsPattern?\\S*)/i";
90+
91+
if (preg_match($defaultPattern, $extra, $matches) === 1) {
92+
$info['defaultValueRaw'] = $matches[1];
93+
$extra = str_replace($matches[0], '', $extra);
94+
}
95+
96+
if (preg_match("/\\s*\\bCHECK\\s+$bracketsPattern/i", $extra, $matches) === 1) {
97+
$info['check'] = substr($matches[1], 1, -1);
98+
$extra = str_replace($matches[0], '', $extra);
99+
}
78100

79-
if (stripos($extra, 'unsigned') !== false) {
101+
$extra = preg_replace('/\s*\bUNSIGNED\b/i', '', $extra, 1, $count);
102+
if ($count > 0) {
80103
$info['unsigned'] = true;
81-
$extra = trim(str_ireplace('unsigned', '', $extra));
82104
}
83105

106+
$extra = preg_replace('/\s*\bUNIQUE\b/i', '', $extra, 1, $count);
107+
if ($count > 0) {
108+
$info['unique'] = true;
109+
}
110+
111+
$extra = preg_replace('/\s*\bNOT\s+NULL\b/i', '', $extra, 1, $count);
112+
if ($count > 0) {
113+
$info['notNull'] = true;
114+
} else {
115+
$extra = preg_replace('/\s*\bNULL\b/i', '', $extra, 1, $count);
116+
if ($count > 0) {
117+
$info['notNull'] = false;
118+
}
119+
}
120+
121+
$extra = trim($extra);
122+
84123
if (!empty($extra)) {
85124
$info['extra'] = $extra;
86125
}

tests/AbstractColumnFactoryTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ public function testFromDefinitionWithExtra(): void
104104
$db = $this->getConnection();
105105
$columnFactory = $db->getSchema()->getColumnFactory();
106106

107-
$column = $columnFactory->fromDefinition('char(1) NOT NULL', ['extra' => 'UNIQUE']);
107+
$column = $columnFactory->fromDefinition('char(1) INVISIBLE', ['extra' => 'COLLATE utf8mb4']);
108108

109109
$this->assertInstanceOf(StringColumnSchema::class, $column);
110110
$this->assertSame('char', $column->getType());
111111
$this->assertSame(1, $column->getSize());
112-
$this->assertSame('NOT NULL UNIQUE', $column->getExtra());
112+
$this->assertSame('INVISIBLE COLLATE utf8mb4', $column->getExtra());
113113

114114
$db->close();
115115
}

tests/Provider/ColumnDefinitionParserProvider.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,21 @@ public static function parse(): array
1313
['int', ['type' => 'int']],
1414
['int(10)', ['type' => 'int', 'size' => 10]],
1515
['int UNSIGNED', ['type' => 'int', 'unsigned' => true]],
16+
['int UNIQUE', ['type' => 'int', 'unique' => true]],
1617
['int(10) UNSIGNED', ['type' => 'int', 'size' => 10, 'unsigned' => true]],
17-
['int(10) UNSIGNED NOT NULL', ['type' => 'int', 'size' => 10, 'unsigned' => true, 'extra' => 'NOT NULL']],
18-
['int(10) NOT NULL', ['type' => 'int', 'size' => 10, 'extra' => 'NOT NULL']],
19-
['text NOT NULL', ['type' => 'text', 'extra' => 'NOT NULL']],
18+
['int(10) UNSIGNED NOT NULL', ['type' => 'int', 'size' => 10, 'unsigned' => true, 'notNull' => true]],
19+
['int(10) NOT NULL', ['type' => 'int', 'size' => 10, 'notNull' => true]],
20+
['text NOT NULL', ['type' => 'text', 'notNull' => true]],
21+
['text NULL', ['type' => 'text', 'notNull' => false]],
22+
['text COLLATE utf8mb4', ['type' => 'text', 'extra' => 'COLLATE utf8mb4']],
23+
['text DEFAULT NULL', ['type' => 'text', 'defaultValueRaw' => 'NULL']],
24+
["text DEFAULT 'value'", ['type' => 'text', 'defaultValueRaw' => "'value'"]],
25+
['varchar(36) DEFAULT uuid()', ['type' => 'varchar', 'size' => 36, 'defaultValueRaw' => 'uuid()']],
26+
['varchar(36) DEFAULT uuid()::varchar(36)', ['type' => 'varchar', 'size' => 36, 'defaultValueRaw' => 'uuid()::varchar(36)']],
27+
['int DEFAULT (1 + 2)', ['type' => 'int', 'defaultValueRaw' => '(1 + 2)']],
28+
['int CHECK (value > (1 + 5))', ['type' => 'int', 'check' => 'value > (1 + 5)']],
2029
["enum('a','b','c')", ['type' => 'enum', 'enumValues' => ['a', 'b', 'c']]],
21-
["enum('a','b','c') NOT NULL", ['type' => 'enum', 'enumValues' => ['a', 'b', 'c'], 'extra' => 'NOT NULL']],
30+
["enum('a','b','c') NOT NULL", ['type' => 'enum', 'enumValues' => ['a', 'b', 'c'], 'notNull' => true]],
2231
];
2332
}
2433
}

tests/Provider/ColumnFactoryProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static function definitions(): array
2424
// definition, expected type, expected instance of, expected column method results
2525
'' => ['', ColumnType::STRING, StringColumnSchema::class, ['getDbType' => '']],
2626
'text' => ['text', ColumnType::TEXT, StringColumnSchema::class, ['getDbType' => 'text']],
27-
'text NOT NULL' => ['text NOT NULL', ColumnType::TEXT, StringColumnSchema::class, ['getDbType' => 'text', 'getExtra' => 'NOT NULL']],
27+
'text NOT NULL' => ['text NOT NULL', ColumnType::TEXT, StringColumnSchema::class, ['getDbType' => 'text', 'isNotNull' => true]],
2828
'char(1)' => ['char(1)', ColumnType::CHAR, StringColumnSchema::class, ['getDbType' => 'char', 'getSize' => 1]],
2929
'decimal(10,2)' => ['decimal(10,2)', ColumnType::DECIMAL, DoubleColumnSchema::class, ['getDbType' => 'decimal', 'getSize' => 10, 'getScale' => 2]],
3030
'bigint UNSIGNED' => ['bigint UNSIGNED', ColumnType::BIGINT, BigIntColumnSchema::class, ['getDbType' => 'bigint', 'isUnsigned' => true]],

0 commit comments

Comments
 (0)