packages/sql-fixture/tests/Unit/Platform/Sqlite/SqliteSchemaFetcherTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Platform\Sqlite;
6
7use PDO;
8use PHPUnit\Framework\Attributes\CoversClass;
9use PHPUnit\Framework\Attributes\Test;
10use PHPUnit\Framework\Attributes\UsesClass;
11use PHPUnit\Framework\TestCase;
12use SqlFixture\Platform\Sqlite\SqliteSchemaFetcher;
13use SqlFixture\Platform\Sqlite\SqliteSchemaParser;
14use SqlFixture\Schema\ColumnDefinition;
15use SqlFixture\Schema\TableSchema;
16
17#[CoversClass(SqliteSchemaFetcher::class)]
18#[UsesClass(SqliteSchemaParser::class)]
19#[UsesClass(ColumnDefinition::class)]
20#[UsesClass(TableSchema::class)]
21#[CoversClass(\SqlFixture\Platform\Sqlite\Schema\CreateTableQuery::class)]
22#[CoversClass(\SqlFixture\Platform\Sqlite\Schema\PragmaColumn::class)]
23#[CoversClass(\SqlFixture\Platform\Sqlite\Schema\PragmaSchema::class)]
24#[UsesClass(\SqlFixture\Schema\SchemaFetcherInterface::class)]
25#[UsesClass(\SqlFixture\Schema\SchemaParseException::class)]
26#[UsesClass(\SqlFixture\Schema\SchemaParserInterface::class)]
27#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\ColumnParser::class)]
28#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\DefaultExpression::class)]
29#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\DefinitionList::class)]
30#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\TableSyntax::class)]
31#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\TypeDeclaration::class)]
32#[UsesClass(\SqlFixture\Schema\DefinitionSegments::class)]
33#[UsesClass(\SqlFixture\Schema\TypeShape::class)]
34#[UsesClass(\SqlFixture\Schema\Exception\InvalidSqlException::class)]
35#[UsesClass(\SqlFixture\Schema\Exception\ExpectedCreateTableException::class)]
36#[UsesClass(\SqlFixture\Schema\Exception\MissingColumnDefinitionsException::class)]
37final class SqliteSchemaFetcherTest extends TestCase
38{
39    #[Test]
40    public function testFetchSchemaFromSqliteTable(): void
41    {
42        $pdo = new PDO('sqlite::memory:');
43        $pdo->exec('CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price REAL)');
44
45        $fetcher = new SqliteSchemaFetcher();
46        $schema = $fetcher->fetchSchema($pdo, 'products');
47
48        self::assertSame('products', $schema->tableName);
49        self::assertTrue($schema->hasColumn('id'));
50        self::assertTrue($schema->hasColumn('name'));
51        self::assertTrue($schema->hasColumn('price'));
52    }
53
54    #[Test]
55    public function testFetchSchemaWithVarcharLength(): void
56    {
57        $pdo = new PDO('sqlite::memory:');
58        $pdo->exec('CREATE TABLE items (id INTEGER PRIMARY KEY, name VARCHAR(100) NOT NULL)');
59
60        $fetcher = new SqliteSchemaFetcher();
61        $schema = $fetcher->fetchSchema($pdo, 'items');
62
63        self::assertSame('VARCHAR', $schema->columns['name']->type);
64        self::assertSame(100, $schema->columns['name']->length);
65        self::assertFalse($schema->columns['name']->nullable);
66    }
67
68    #[Test]
69    public function testFetchSchemaWithDecimalPrecisionScale(): void
70    {
71        $pdo = new PDO('sqlite::memory:');
72        $pdo->exec('CREATE TABLE money (id INTEGER PRIMARY KEY, amount DECIMAL(10, 2))');
73
74        $fetcher = new SqliteSchemaFetcher();
75        $schema = $fetcher->fetchSchema($pdo, 'money');
76
77        self::assertSame('DECIMAL', $schema->columns['amount']->type);
78        self::assertSame(10, $schema->columns['amount']->precision);
79        self::assertSame(2, $schema->columns['amount']->scale);
80    }
81
82    #[Test]
83    public function testFetchSchemaWithDefaultValues(): void
84    {
85        $pdo = new PDO('sqlite::memory:');
86        $pdo->exec("CREATE TABLE defaults (
87            id INTEGER PRIMARY KEY,
88            count INTEGER DEFAULT 42,
89            name TEXT DEFAULT 'hello',
90            nullable TEXT DEFAULT NULL,
91            price REAL DEFAULT 9.99
92        )");
93
94        $fetcher = new SqliteSchemaFetcher();
95        $schema = $fetcher->fetchSchema($pdo, 'defaults');
96
97        self::assertSame(42, $schema->columns['count']->default);
98        self::assertSame('hello', $schema->columns['name']->default);
99        self::assertNull($schema->columns['nullable']->default);
100        self::assertSame(9.99, $schema->columns['price']->default);
101    }
102
103    #[Test]
104    public function testFetchSchemaWithNullableColumns(): void
105    {
106        $pdo = new PDO('sqlite::memory:');
107        $pdo->exec('CREATE TABLE test (id INTEGER NOT NULL, name TEXT)');
108
109        $fetcher = new SqliteSchemaFetcher();
110        $schema = $fetcher->fetchSchema($pdo, 'test');
111
112        self::assertFalse($schema->columns['id']->nullable);
113        self::assertTrue($schema->columns['name']->nullable);
114    }
115
116    #[Test]
117    public function testFetchSchemaWithAutoincrement(): void
118    {
119        $pdo = new PDO('sqlite::memory:');
120        $pdo->exec('CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)');
121
122        $fetcher = new SqliteSchemaFetcher();
123        $schema = $fetcher->fetchSchema($pdo, 'test');
124
125        self::assertTrue($schema->columns['id']->autoIncrement);
126    }
127
128    #[Test]
129    public function testFetchSchemaWithCustomParser(): void
130    {
131        $pdo = new PDO('sqlite::memory:');
132        $pdo->exec('CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)');
133
134        $parser = new SqliteSchemaParser();
135        $fetcher = new SqliteSchemaFetcher($parser);
136        $schema = $fetcher->fetchSchema($pdo, 'test');
137
138        self::assertSame('test', $schema->tableName);
139    }
140
141    #[Test]
142    public function testFetchSchemaWithDefaultCurrentTimestamp(): void
143    {
144        $pdo = new PDO('sqlite::memory:');
145        $pdo->exec('CREATE TABLE test (id INTEGER PRIMARY KEY, created_at TEXT DEFAULT CURRENT_TIMESTAMP)');
146
147        $fetcher = new SqliteSchemaFetcher();
148        $schema = $fetcher->fetchSchema($pdo, 'test');
149
150        self::assertSame('CURRENT_TIMESTAMP', $schema->columns['created_at']->default);
151    }
152}
153