Skip to content

Commit 6d0f5eb

Browse files
committed
sqlite.. work in progress
1 parent 5276220 commit 6d0f5eb

File tree

5 files changed

+184
-58
lines changed

5 files changed

+184
-58
lines changed

api.php

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4006,8 +4006,31 @@ public function updateTable(string $tableName, /* object */ $changes): bool
40064006
return true;
40074007
}
40084008

4009+
public function updateColumnSqlite(string $tableName, string $columnName, /* object */ $changes): bool
4010+
{
4011+
$table = $this->reflection->getTable($tableName);
4012+
$column = $table->getColumn($columnName);
4013+
4014+
// remove constraints on other column
4015+
$newColumn = ReflectedColumn::fromJson((object) array_merge((array) $column->jsonSerialize(), (array) $changes));
4016+
$columns = [];
4017+
foreach ($table->getColumnNames() as $name) {
4018+
if ($name == $columnName) {
4019+
$columns[] = $newColumn;
4020+
} else {
4021+
$columns[] = $table->getColumn($name);
4022+
}
4023+
}
4024+
$newTable = new ReflectedTable($table->getName(), $table->getType(), $columns);
4025+
return $this->db->definition()->updateColumnsSqlite($newTable);
4026+
}
4027+
40094028
public function updateColumn(string $tableName, string $columnName, /* object */ $changes): bool
40104029
{
4030+
if ($this->db->getDriver() == 'sqlite') {
4031+
return $this->updateColumnSqlite($tableName, $columnName, $changes);
4032+
}
4033+
40114034
$table = $this->reflection->getTable($tableName);
40124035
$column = $table->getColumn($columnName);
40134036

@@ -4045,7 +4068,8 @@ public function updateColumn(string $tableName, string $columnName, /* object */
40454068
return false;
40464069
}
40474070
}
4048-
if ($newColumn->getType() != $column->getType() ||
4071+
if (
4072+
$newColumn->getType() != $column->getType() ||
40494073
$newColumn->getLength() != $column->getLength() ||
40504074
$newColumn->getPrecision() != $column->getPrecision() ||
40514075
$newColumn->getScale() != $column->getScale()
@@ -5270,6 +5294,11 @@ class GenericDB
52705294
private $columns;
52715295
private $converter;
52725296

5297+
public function getDriver(): string
5298+
{
5299+
return $this->driver;
5300+
}
5301+
52735302
private function getDsn(): string
52745303
{
52755304
switch ($this->driver) {
@@ -5302,6 +5331,7 @@ private function getCommands(): array
53025331
case 'sqlite':
53035332
return [
53045333
'PRAGMA foreign_keys = on;',
5334+
'PRAGMA writable_schema = on;',
53055335
];
53065336
}
53075337
}
@@ -5661,6 +5691,8 @@ private function getColumnAutoIncrement(ReflectedColumn $column, bool $update):
56615691
case 'pgsql':
56625692
case 'sqlsrv':
56635693
return '';
5694+
case 'sqlite':
5695+
return $column->getPk() ? ' AUTOINCREMENT' : '';
56645696
}
56655697
}
56665698

@@ -5684,6 +5716,8 @@ private function getTableRenameSQL(string $tableName, string $newTableName): str
56845716
return "ALTER TABLE $p1 RENAME TO $p2";
56855717
case 'sqlsrv':
56865718
return "EXEC sp_rename $p1, $p2";
5719+
case 'sqlite':
5720+
return "ALTER TABLE $p1 RENAME TO $p2";
56875721
}
56885722
}
56895723

@@ -5702,6 +5736,8 @@ private function getColumnRenameSQL(string $tableName, string $columnName, Refle
57025736
case 'sqlsrv':
57035737
$p4 = $this->quote($tableName . '.' . $columnName);
57045738
return "EXEC sp_rename $p4, $p3, 'COLUMN'";
5739+
case 'sqlite':
5740+
return "ALTER TABLE $p1 RENAME COLUMN $p2 TO $p3";
57055741
}
57065742
}
57075743

@@ -5860,12 +5896,22 @@ private function getAddTableSQL(ReflectedTable $newTable): string
58605896
$f4 = $this->quote($newColumn->getFk());
58615897
$f5 = $this->quote($this->getPrimaryKey($newColumn->getFk()));
58625898
$f6 = $this->quote($tableName . '_' . $pkColumn . '_pkey');
5863-
$fields[] = "$f1 $f2";
5864-
if ($newColumn->getPk()) {
5865-
$constraints[] = "CONSTRAINT $f6 PRIMARY KEY ($f1)";
5866-
}
5867-
if ($newColumn->getFk()) {
5868-
$constraints[] = "CONSTRAINT $f3 FOREIGN KEY ($f1) REFERENCES $f4 ($f5)";
5899+
if ($this->driver == 'sqlite') {
5900+
if ($newColumn->getPk()) {
5901+
$f2 = str_replace('NULL', 'NULL PRIMARY KEY', $f2);
5902+
}
5903+
$fields[] = "$f1 $f2";
5904+
if ($newColumn->getFk()) {
5905+
$constraints[] = "FOREIGN KEY ($f1) REFERENCES $f4 ($f5)";
5906+
}
5907+
} else {
5908+
$fields[] = "$f1 $f2";
5909+
if ($newColumn->getPk()) {
5910+
$constraints[] = "CONSTRAINT $f6 PRIMARY KEY ($f1)";
5911+
}
5912+
if ($newColumn->getFk()) {
5913+
$constraints[] = "CONSTRAINT $f3 FOREIGN KEY ($f1) REFERENCES $f4 ($f5)";
5914+
}
58695915
}
58705916
}
58715917
$p2 = implode(',', array_merge($fields, $constraints));
@@ -5885,6 +5931,8 @@ private function getAddColumnSQL(string $tableName, ReflectedColumn $newColumn):
58855931
return "ALTER TABLE $p1 ADD COLUMN $p2 $p3";
58865932
case 'sqlsrv':
58875933
return "ALTER TABLE $p1 ADD $p2 $p3";
5934+
case 'sqlite':
5935+
return "ALTER TABLE $p1 ADD COLUMN $p2 $p3";
58885936
}
58895937
}
58905938

@@ -5898,6 +5946,8 @@ private function getRemoveTableSQL(string $tableName): string
58985946
return "DROP TABLE $p1 CASCADE;";
58995947
case 'sqlsrv':
59005948
return "DROP TABLE $p1;";
5949+
case 'sqlite':
5950+
return "DROP TABLE $p1;";
59015951
}
59025952
}
59035953

@@ -5912,44 +5962,56 @@ private function getRemoveColumnSQL(string $tableName, string $columnName): stri
59125962
return "ALTER TABLE $p1 DROP COLUMN $p2 CASCADE;";
59135963
case 'sqlsrv':
59145964
return "ALTER TABLE $p1 DROP COLUMN $p2;";
5965+
case 'sqlite':
5966+
return "ALTER TABLE $p1 DROP COLUMN $p2;";
59155967
}
59165968
}
59175969

59185970
public function renameTable(string $tableName, string $newTableName)
59195971
{
59205972
$sql = $this->getTableRenameSQL($tableName, $newTableName);
5921-
return $this->query($sql);
5973+
return $this->query($sql, []);
59225974
}
59235975

59245976
public function renameColumn(string $tableName, string $columnName, ReflectedColumn $newColumn)
59255977
{
59265978
$sql = $this->getColumnRenameSQL($tableName, $columnName, $newColumn);
5927-
return $this->query($sql);
5979+
return $this->query($sql, []);
5980+
}
5981+
5982+
public function updateColumnsSqlite(ReflectedTable $table)
5983+
{
5984+
$create = $this->getAddTableSQL($table);
5985+
$name = $table->getName();
5986+
$sql = "UPDATE SQLITE_MASTER SET SQL = ? WHERE NAME = ?;";
5987+
$result = $this->query($sql, [$create, $name]);
5988+
$this->query('VACUUM;', []);
5989+
return $result;
59285990
}
59295991

59305992
public function retypeColumn(string $tableName, string $columnName, ReflectedColumn $newColumn)
59315993
{
59325994
$sql = $this->getColumnRetypeSQL($tableName, $columnName, $newColumn);
5933-
return $this->query($sql);
5995+
return $this->query($sql, []);
59345996
}
59355997

59365998
public function setColumnNullable(string $tableName, string $columnName, ReflectedColumn $newColumn)
59375999
{
59386000
$sql = $this->getSetColumnNullableSQL($tableName, $columnName, $newColumn);
5939-
return $this->query($sql);
6001+
return $this->query($sql, []);
59406002
}
59416003

59426004
public function addColumnPrimaryKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
59436005
{
59446006
$sql = $this->getSetColumnPkConstraintSQL($tableName, $columnName, $newColumn);
5945-
$this->query($sql);
6007+
$this->query($sql, []);
59466008
if ($this->canAutoIncrement($newColumn)) {
59476009
$sql = $this->getSetColumnPkSequenceSQL($tableName, $columnName, $newColumn);
5948-
$this->query($sql);
6010+
$this->query($sql, []);
59496011
$sql = $this->getSetColumnPkSequenceStartSQL($tableName, $columnName, $newColumn);
5950-
$this->query($sql);
6012+
$this->query($sql, []);
59516013
$sql = $this->getSetColumnPkDefaultSQL($tableName, $columnName, $newColumn);
5952-
$this->query($sql);
6014+
$this->query($sql, []);
59536015
}
59546016
return true;
59556017
}
@@ -5958,56 +6020,56 @@ public function removeColumnPrimaryKey(string $tableName, string $columnName, Re
59586020
{
59596021
if ($this->canAutoIncrement($newColumn)) {
59606022
$sql = $this->getSetColumnPkDefaultSQL($tableName, $columnName, $newColumn);
5961-
$this->query($sql);
6023+
$this->query($sql, []);
59626024
$sql = $this->getSetColumnPkSequenceSQL($tableName, $columnName, $newColumn);
5963-
$this->query($sql);
6025+
$this->query($sql, []);
59646026
}
59656027
$sql = $this->getSetColumnPkConstraintSQL($tableName, $columnName, $newColumn);
5966-
$this->query($sql);
6028+
$this->query($sql, []);
59676029
return true;
59686030
}
59696031

59706032
public function addColumnForeignKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
59716033
{
59726034
$sql = $this->getAddColumnFkConstraintSQL($tableName, $columnName, $newColumn);
5973-
return $this->query($sql);
6035+
return $this->query($sql, []);
59746036
}
59756037

59766038
public function removeColumnForeignKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
59776039
{
59786040
$sql = $this->getRemoveColumnFkConstraintSQL($tableName, $columnName, $newColumn);
5979-
return $this->query($sql);
6041+
return $this->query($sql, []);
59806042
}
59816043

59826044
public function addTable(ReflectedTable $newTable)
59836045
{
59846046
$sql = $this->getAddTableSQL($newTable);
5985-
return $this->query($sql);
6047+
return $this->query($sql, []);
59866048
}
59876049

59886050
public function addColumn(string $tableName, ReflectedColumn $newColumn)
59896051
{
59906052
$sql = $this->getAddColumnSQL($tableName, $newColumn);
5991-
return $this->query($sql);
6053+
return $this->query($sql, []);
59926054
}
59936055

59946056
public function removeTable(string $tableName)
59956057
{
59966058
$sql = $this->getRemoveTableSQL($tableName);
5997-
return $this->query($sql);
6059+
return $this->query($sql, []);
59986060
}
59996061

60006062
public function removeColumn(string $tableName, string $columnName)
60016063
{
60026064
$sql = $this->getRemoveColumnSQL($tableName, $columnName);
6003-
return $this->query($sql);
6065+
return $this->query($sql, []);
60046066
}
60056067

6006-
private function query(string $sql): bool
6068+
private function query(string $sql, array $arguments): bool
60076069
{
60086070
$stmt = $this->pdo->prepare($sql);
6009-
//echo "- $sql -- []\n";
6010-
return $stmt->execute();
6071+
//echo "- $sql -- " . json_encode($arguments) . "\n";
6072+
return $stmt->execute($arguments);
60116073
}
60126074
}
60136075
}
@@ -6034,7 +6096,7 @@ public function __construct(LazyPdo $pdo, string $driver, string $database, arra
60346096
$this->typeConverter = new TypeConverter($driver);
60356097
}
60366098

6037-
private function createSqlLiteReflectionTables() /*: void */
6099+
private function updateSqlLiteReflectionTables() /*: void */
60386100
{
60396101
$reflection = $this->query('SELECT "name" FROM "sqlite_master" WHERE "type" = \'table\' and name like \'sys/%\';', []);
60406102
if (count($reflection) == 0) {
@@ -6103,7 +6165,7 @@ private function getTablesSQL(): string
61036165
case 'sqlsrv':
61046166
return 'SELECT o.name as "TABLE_NAME", o.xtype as "TABLE_TYPE" FROM sysobjects o WHERE o.xtype IN (\'U\', \'V\') ORDER BY "TABLE_NAME"';
61056167
case 'sqlite':
6106-
$this->createSqlLiteReflectionTables();
6168+
$this->updateSqlLiteReflectionTables();
61076169
return 'SELECT t.name as "TABLE_NAME", t.type as "TABLE_TYPE" FROM "sys/tables" t WHERE t.type IN (\'table\', \'view\') AND \'\' <> ? ORDER BY "TABLE_NAME"';
61086170
}
61096171
}
@@ -6118,6 +6180,7 @@ private function getTableColumnsSQL(): string
61186180
case 'sqlsrv':
61196181
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
61206182
case 'sqlite':
6183+
$this->updateSqlLiteReflectionTables();
61216184
return 'SELECT "name" AS "COLUMN_NAME", case when "notnull"==1 then \'no\' else \'yes\' end as "IS_NULLABLE", "type" AS "DATA_TYPE", 2147483647 AS "CHARACTER_MAXIMUM_LENGTH", 0 AS "NUMERIC_PRECISION", 0 AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM "sys/columns" WHERE "self" = ? AND \'\' <> ?';
61226185
}
61236186
}

src/Tqdev/PhpCrudApi/Column/DefinitionService.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,31 @@ public function updateTable(string $tableName, /* object */ $changes): bool
2929
return true;
3030
}
3131

32+
public function updateColumnSqlite(string $tableName, string $columnName, /* object */ $changes): bool
33+
{
34+
$table = $this->reflection->getTable($tableName);
35+
$column = $table->getColumn($columnName);
36+
37+
// remove constraints on other column
38+
$newColumn = ReflectedColumn::fromJson((object) array_merge((array) $column->jsonSerialize(), (array) $changes));
39+
$columns = [];
40+
foreach ($table->getColumnNames() as $name) {
41+
if ($name == $columnName) {
42+
$columns[] = $newColumn;
43+
} else {
44+
$columns[] = $table->getColumn($name);
45+
}
46+
}
47+
$newTable = new ReflectedTable($table->getName(), $table->getType(), $columns);
48+
return $this->db->definition()->updateColumnsSqlite($newTable);
49+
}
50+
3251
public function updateColumn(string $tableName, string $columnName, /* object */ $changes): bool
3352
{
53+
if ($this->db->getDriver() == 'sqlite') {
54+
return $this->updateColumnSqlite($tableName, $columnName, $changes);
55+
}
56+
3457
$table = $this->reflection->getTable($tableName);
3558
$column = $table->getColumn($columnName);
3659

@@ -68,7 +91,8 @@ public function updateColumn(string $tableName, string $columnName, /* object */
6891
return false;
6992
}
7093
}
71-
if ($newColumn->getType() != $column->getType() ||
94+
if (
95+
$newColumn->getType() != $column->getType() ||
7296
$newColumn->getLength() != $column->getLength() ||
7397
$newColumn->getPrecision() != $column->getPrecision() ||
7498
$newColumn->getScale() != $column->getScale()

src/Tqdev/PhpCrudApi/Database/GenericDB.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ class GenericDB
2323
private $columns;
2424
private $converter;
2525

26+
public function getDriver(): string
27+
{
28+
return $this->driver;
29+
}
30+
2631
private function getDsn(): string
2732
{
2833
switch ($this->driver) {
@@ -55,6 +60,7 @@ private function getCommands(): array
5560
case 'sqlite':
5661
return [
5762
'PRAGMA foreign_keys = on;',
63+
'PRAGMA writable_schema = on;',
5864
];
5965
}
6066
}

0 commit comments

Comments
 (0)