Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
1 change: 1 addition & 0 deletions src/Column/ColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ protected function getDbType(ColumnInterface $column): string
ColumnType::ARRAY => 'json',
ColumnType::STRUCTURED => 'json',
ColumnType::JSON => 'json',
ColumnType::ENUM => 'varchar',
Comment thread
vjik marked this conversation as resolved.
default => 'varchar',
};
}
Expand Down
1 change: 0 additions & 1 deletion src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ final class ColumnFactory extends AbstractColumnFactory
'numeric' => ColumnType::DECIMAL,
'char' => ColumnType::CHAR,
'varchar' => ColumnType::STRING,
'enum' => ColumnType::STRING,
'tinytext' => ColumnType::TEXT,
'mediumtext' => ColumnType::TEXT,
'longtext' => ColumnType::TEXT,
Expand Down
44 changes: 42 additions & 2 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ protected function findColumns(TableSchemaInterface $table): bool
{
$columns = $this->loadTableColumnsInfo($table->getName());
$jsonColumns = $this->getJsonColumns($table);
$checks = $this->loadTableChecks($table->getName());
Comment thread
Tigrov marked this conversation as resolved.
Outdated

foreach ($columns as $info) {
if (in_array($info['name'], $jsonColumns, true)) {
Expand All @@ -252,7 +253,7 @@ protected function findColumns(TableSchemaInterface $table): bool
$info['schema'] = $table->getSchemaName();
$info['table'] = $table->getName();

$column = $this->loadColumn($info);
$column = $this->loadColumn($info, $checks);
$table->column($info['name'], $column);
}

Expand Down Expand Up @@ -314,12 +315,13 @@ protected function findViewNames(string $schema = ''): array
* Loads the column information into a {@see ColumnInterface} object.
*
* @param array $info The column information.
* @param Check[] $checks
*
* @return ColumnInterface The column object.
*
* @psalm-param ColumnInfo $info
*/
private function loadColumn(array $info): ColumnInterface
private function loadColumn(array $info, array $checks): ColumnInterface
{
return $this->db->getColumnFactory()->fromDefinition($info['type'], [
'defaultValueRaw' => $info['dflt_value'],
Expand All @@ -328,6 +330,7 @@ private function loadColumn(array $info): ColumnInterface
'primaryKey' => (bool) $info['pk'],
'schema' => $info['schema'],
'table' => $info['table'],
'values' => $this->tryGetEnumValuesFromCheck($info['name'], $checks),
]);
}

Expand Down Expand Up @@ -397,4 +400,41 @@ private function getJsonColumns(TableSchemaInterface $table): array

return $result;
}

/**
* @param Check[] $checks
*
* @psalm-return list<string>|null
*/
private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array
{
Comment thread
vjik marked this conversation as resolved.
if (empty($checks)) {
return null;
}

foreach ($checks as $check) {
if (!str_starts_with($check->expression, "$name ")) {
Comment thread
Tigrov marked this conversation as resolved.
Outdated
continue;
}

preg_match_all(
"~ IN\s*\(\s*(?:'(?:[^']+|'(?:''|[^']))*')+~i",
Comment thread
Tigrov marked this conversation as resolved.
Outdated
$check->expression,
$block,
);

if (empty($block[0][0])) {
continue;
}

preg_match_all("~'((?:''|[^'])*)'~", $block[0][0], $matches);
Comment thread
vjik marked this conversation as resolved.

return array_map(
static fn($v) => str_replace("''", "'", $v),
$matches[1] ?? [],
);
}

return null;
}
}
55 changes: 55 additions & 0 deletions tests/Column/EnumColumnTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Sqlite\Tests\Column;

use PHPUnit\Framework\Attributes\TestWith;
use Yiisoft\Db\Schema\Column\EnumColumn;
use Yiisoft\Db\Sqlite\Tests\Support\IntegrationTestTrait;
use Yiisoft\Db\Tests\Common\CommonEnumColumnTest;

final class EnumColumnTest extends CommonEnumColumnTest
{
use IntegrationTestTrait;

#[TestWith(['INTEGER CHECK (status IN (1, 2, 3))'])]
public function testNonEnumCheck(string $columnDefinition): void
{
$this->dropTable('test_enum_table');
$this->executeStatements(
<<<SQL
CREATE TABLE test_enum_table (
id INTEGER,
status $columnDefinition
)
SQL,
);

$db = $this->getSharedConnection();
$column = $db->getTableSchema('test_enum_table')->getColumn('status');

$this->assertNotInstanceOf(EnumColumn::class, $column);

$this->dropTable('test_enum_table');
}

protected function createDatabaseObjectsStatements(): array
{
return [
<<<SQL
CREATE TABLE tbl_enum (
id INTEGER,
status TEXT CHECK(status IN ('active', 'unactive', 'pending'))
Comment thread
vjik marked this conversation as resolved.
Comment thread
vjik marked this conversation as resolved.
)
SQL,
];
}

protected function dropDatabaseObjectsStatements(): array
{
return [
'DROP TABLE IF EXISTS tbl_enum',
];
}
}
1 change: 0 additions & 1 deletion tests/Provider/ColumnFactoryProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public static function dbTypes(): array
['char', ColumnType::CHAR, StringColumn::class],
['varchar', ColumnType::STRING, StringColumn::class],
['string', ColumnType::STRING, StringColumn::class],
['enum', ColumnType::STRING, StringColumn::class],
['tinytext', ColumnType::TEXT, StringColumn::class],
['mediumtext', ColumnType::TEXT, StringColumn::class],
['longtext', ColumnType::TEXT, StringColumn::class],
Expand Down
Loading