|
@@ -4006,8 +4006,31 @@ namespace Tqdev\PhpCrudApi\Column {
|
4006
|
4006
|
return true;
|
4007
|
4007
|
}
|
4008
|
4008
|
|
|
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
|
+
|
4009
|
4028
|
public function updateColumn(string $tableName, string $columnName, /* object */ $changes): bool
|
4010
|
4029
|
{
|
|
4030
|
+ if ($this->db->getDriver() == 'sqlite') {
|
|
4031
|
+ return $this->updateColumnSqlite($tableName, $columnName, $changes);
|
|
4032
|
+ }
|
|
4033
|
+
|
4011
|
4034
|
$table = $this->reflection->getTable($tableName);
|
4012
|
4035
|
$column = $table->getColumn($columnName);
|
4013
|
4036
|
|
|
@@ -4045,7 +4068,8 @@ namespace Tqdev\PhpCrudApi\Column {
|
4045
|
4068
|
return false;
|
4046
|
4069
|
}
|
4047
|
4070
|
}
|
4048
|
|
- if ($newColumn->getType() != $column->getType() ||
|
|
4071
|
+ if (
|
|
4072
|
+ $newColumn->getType() != $column->getType() ||
|
4049
|
4073
|
$newColumn->getLength() != $column->getLength() ||
|
4050
|
4074
|
$newColumn->getPrecision() != $column->getPrecision() ||
|
4051
|
4075
|
$newColumn->getScale() != $column->getScale()
|
|
@@ -5270,6 +5294,11 @@ namespace Tqdev\PhpCrudApi\Database {
|
5270
|
5294
|
private $columns;
|
5271
|
5295
|
private $converter;
|
5272
|
5296
|
|
|
5297
|
+ public function getDriver(): string
|
|
5298
|
+ {
|
|
5299
|
+ return $this->driver;
|
|
5300
|
+ }
|
|
5301
|
+
|
5273
|
5302
|
private function getDsn(): string
|
5274
|
5303
|
{
|
5275
|
5304
|
switch ($this->driver) {
|
|
@@ -5302,6 +5331,7 @@ namespace Tqdev\PhpCrudApi\Database {
|
5302
|
5331
|
case 'sqlite':
|
5303
|
5332
|
return [
|
5304
|
5333
|
'PRAGMA foreign_keys = on;',
|
|
5334
|
+ 'PRAGMA writable_schema = on;',
|
5305
|
5335
|
];
|
5306
|
5336
|
}
|
5307
|
5337
|
}
|
|
@@ -5661,6 +5691,8 @@ namespace Tqdev\PhpCrudApi\Database {
|
5661
|
5691
|
case 'pgsql':
|
5662
|
5692
|
case 'sqlsrv':
|
5663
|
5693
|
return '';
|
|
5694
|
+ case 'sqlite':
|
|
5695
|
+ return $column->getPk() ? ' AUTOINCREMENT' : '';
|
5664
|
5696
|
}
|
5665
|
5697
|
}
|
5666
|
5698
|
|
|
@@ -5684,6 +5716,8 @@ namespace Tqdev\PhpCrudApi\Database {
|
5684
|
5716
|
return "ALTER TABLE $p1 RENAME TO $p2";
|
5685
|
5717
|
case 'sqlsrv':
|
5686
|
5718
|
return "EXEC sp_rename $p1, $p2";
|
|
5719
|
+ case 'sqlite':
|
|
5720
|
+ return "ALTER TABLE $p1 RENAME TO $p2";
|
5687
|
5721
|
}
|
5688
|
5722
|
}
|
5689
|
5723
|
|
|
@@ -5702,6 +5736,8 @@ namespace Tqdev\PhpCrudApi\Database {
|
5702
|
5736
|
case 'sqlsrv':
|
5703
|
5737
|
$p4 = $this->quote($tableName . '.' . $columnName);
|
5704
|
5738
|
return "EXEC sp_rename $p4, $p3, 'COLUMN'";
|
|
5739
|
+ case 'sqlite':
|
|
5740
|
+ return "ALTER TABLE $p1 RENAME COLUMN $p2 TO $p3";
|
5705
|
5741
|
}
|
5706
|
5742
|
}
|
5707
|
5743
|
|
|
@@ -5860,12 +5896,22 @@ namespace Tqdev\PhpCrudApi\Database {
|
5860
|
5896
|
$f4 = $this->quote($newColumn->getFk());
|
5861
|
5897
|
$f5 = $this->quote($this->getPrimaryKey($newColumn->getFk()));
|
5862
|
5898
|
$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
|
+ }
|
5869
|
5915
|
}
|
5870
|
5916
|
}
|
5871
|
5917
|
$p2 = implode(',', array_merge($fields, $constraints));
|
|
@@ -5885,6 +5931,8 @@ namespace Tqdev\PhpCrudApi\Database {
|
5885
|
5931
|
return "ALTER TABLE $p1 ADD COLUMN $p2 $p3";
|
5886
|
5932
|
case 'sqlsrv':
|
5887
|
5933
|
return "ALTER TABLE $p1 ADD $p2 $p3";
|
|
5934
|
+ case 'sqlite':
|
|
5935
|
+ return "ALTER TABLE $p1 ADD COLUMN $p2 $p3";
|
5888
|
5936
|
}
|
5889
|
5937
|
}
|
5890
|
5938
|
|
|
@@ -5898,6 +5946,8 @@ namespace Tqdev\PhpCrudApi\Database {
|
5898
|
5946
|
return "DROP TABLE $p1 CASCADE;";
|
5899
|
5947
|
case 'sqlsrv':
|
5900
|
5948
|
return "DROP TABLE $p1;";
|
|
5949
|
+ case 'sqlite':
|
|
5950
|
+ return "DROP TABLE $p1;";
|
5901
|
5951
|
}
|
5902
|
5952
|
}
|
5903
|
5953
|
|
|
@@ -5912,44 +5962,56 @@ namespace Tqdev\PhpCrudApi\Database {
|
5912
|
5962
|
return "ALTER TABLE $p1 DROP COLUMN $p2 CASCADE;";
|
5913
|
5963
|
case 'sqlsrv':
|
5914
|
5964
|
return "ALTER TABLE $p1 DROP COLUMN $p2;";
|
|
5965
|
+ case 'sqlite':
|
|
5966
|
+ return "ALTER TABLE $p1 DROP COLUMN $p2;";
|
5915
|
5967
|
}
|
5916
|
5968
|
}
|
5917
|
5969
|
|
5918
|
5970
|
public function renameTable(string $tableName, string $newTableName)
|
5919
|
5971
|
{
|
5920
|
5972
|
$sql = $this->getTableRenameSQL($tableName, $newTableName);
|
5921
|
|
- return $this->query($sql);
|
|
5973
|
+ return $this->query($sql, []);
|
5922
|
5974
|
}
|
5923
|
5975
|
|
5924
|
5976
|
public function renameColumn(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5925
|
5977
|
{
|
5926
|
5978
|
$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;
|
5928
|
5990
|
}
|
5929
|
5991
|
|
5930
|
5992
|
public function retypeColumn(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5931
|
5993
|
{
|
5932
|
5994
|
$sql = $this->getColumnRetypeSQL($tableName, $columnName, $newColumn);
|
5933
|
|
- return $this->query($sql);
|
|
5995
|
+ return $this->query($sql, []);
|
5934
|
5996
|
}
|
5935
|
5997
|
|
5936
|
5998
|
public function setColumnNullable(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5937
|
5999
|
{
|
5938
|
6000
|
$sql = $this->getSetColumnNullableSQL($tableName, $columnName, $newColumn);
|
5939
|
|
- return $this->query($sql);
|
|
6001
|
+ return $this->query($sql, []);
|
5940
|
6002
|
}
|
5941
|
6003
|
|
5942
|
6004
|
public function addColumnPrimaryKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5943
|
6005
|
{
|
5944
|
6006
|
$sql = $this->getSetColumnPkConstraintSQL($tableName, $columnName, $newColumn);
|
5945
|
|
- $this->query($sql);
|
|
6007
|
+ $this->query($sql, []);
|
5946
|
6008
|
if ($this->canAutoIncrement($newColumn)) {
|
5947
|
6009
|
$sql = $this->getSetColumnPkSequenceSQL($tableName, $columnName, $newColumn);
|
5948
|
|
- $this->query($sql);
|
|
6010
|
+ $this->query($sql, []);
|
5949
|
6011
|
$sql = $this->getSetColumnPkSequenceStartSQL($tableName, $columnName, $newColumn);
|
5950
|
|
- $this->query($sql);
|
|
6012
|
+ $this->query($sql, []);
|
5951
|
6013
|
$sql = $this->getSetColumnPkDefaultSQL($tableName, $columnName, $newColumn);
|
5952
|
|
- $this->query($sql);
|
|
6014
|
+ $this->query($sql, []);
|
5953
|
6015
|
}
|
5954
|
6016
|
return true;
|
5955
|
6017
|
}
|
|
@@ -5958,56 +6020,56 @@ namespace Tqdev\PhpCrudApi\Database {
|
5958
|
6020
|
{
|
5959
|
6021
|
if ($this->canAutoIncrement($newColumn)) {
|
5960
|
6022
|
$sql = $this->getSetColumnPkDefaultSQL($tableName, $columnName, $newColumn);
|
5961
|
|
- $this->query($sql);
|
|
6023
|
+ $this->query($sql, []);
|
5962
|
6024
|
$sql = $this->getSetColumnPkSequenceSQL($tableName, $columnName, $newColumn);
|
5963
|
|
- $this->query($sql);
|
|
6025
|
+ $this->query($sql, []);
|
5964
|
6026
|
}
|
5965
|
6027
|
$sql = $this->getSetColumnPkConstraintSQL($tableName, $columnName, $newColumn);
|
5966
|
|
- $this->query($sql);
|
|
6028
|
+ $this->query($sql, []);
|
5967
|
6029
|
return true;
|
5968
|
6030
|
}
|
5969
|
6031
|
|
5970
|
6032
|
public function addColumnForeignKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5971
|
6033
|
{
|
5972
|
6034
|
$sql = $this->getAddColumnFkConstraintSQL($tableName, $columnName, $newColumn);
|
5973
|
|
- return $this->query($sql);
|
|
6035
|
+ return $this->query($sql, []);
|
5974
|
6036
|
}
|
5975
|
6037
|
|
5976
|
6038
|
public function removeColumnForeignKey(string $tableName, string $columnName, ReflectedColumn $newColumn)
|
5977
|
6039
|
{
|
5978
|
6040
|
$sql = $this->getRemoveColumnFkConstraintSQL($tableName, $columnName, $newColumn);
|
5979
|
|
- return $this->query($sql);
|
|
6041
|
+ return $this->query($sql, []);
|
5980
|
6042
|
}
|
5981
|
6043
|
|
5982
|
6044
|
public function addTable(ReflectedTable $newTable)
|
5983
|
6045
|
{
|
5984
|
6046
|
$sql = $this->getAddTableSQL($newTable);
|
5985
|
|
- return $this->query($sql);
|
|
6047
|
+ return $this->query($sql, []);
|
5986
|
6048
|
}
|
5987
|
6049
|
|
5988
|
6050
|
public function addColumn(string $tableName, ReflectedColumn $newColumn)
|
5989
|
6051
|
{
|
5990
|
6052
|
$sql = $this->getAddColumnSQL($tableName, $newColumn);
|
5991
|
|
- return $this->query($sql);
|
|
6053
|
+ return $this->query($sql, []);
|
5992
|
6054
|
}
|
5993
|
6055
|
|
5994
|
6056
|
public function removeTable(string $tableName)
|
5995
|
6057
|
{
|
5996
|
6058
|
$sql = $this->getRemoveTableSQL($tableName);
|
5997
|
|
- return $this->query($sql);
|
|
6059
|
+ return $this->query($sql, []);
|
5998
|
6060
|
}
|
5999
|
6061
|
|
6000
|
6062
|
public function removeColumn(string $tableName, string $columnName)
|
6001
|
6063
|
{
|
6002
|
6064
|
$sql = $this->getRemoveColumnSQL($tableName, $columnName);
|
6003
|
|
- return $this->query($sql);
|
|
6065
|
+ return $this->query($sql, []);
|
6004
|
6066
|
}
|
6005
|
6067
|
|
6006
|
|
- private function query(string $sql): bool
|
|
6068
|
+ private function query(string $sql, array $arguments): bool
|
6007
|
6069
|
{
|
6008
|
6070
|
$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);
|
6011
|
6073
|
}
|
6012
|
6074
|
}
|
6013
|
6075
|
}
|
|
@@ -6034,7 +6096,7 @@ namespace Tqdev\PhpCrudApi\Database {
|
6034
|
6096
|
$this->typeConverter = new TypeConverter($driver);
|
6035
|
6097
|
}
|
6036
|
6098
|
|
6037
|
|
- private function createSqlLiteReflectionTables() /*: void */
|
|
6099
|
+ private function updateSqlLiteReflectionTables() /*: void */
|
6038
|
6100
|
{
|
6039
|
6101
|
$reflection = $this->query('SELECT "name" FROM "sqlite_master" WHERE "type" = \'table\' and name like \'sys/%\';', []);
|
6040
|
6102
|
if (count($reflection) == 0) {
|
|
@@ -6103,7 +6165,7 @@ namespace Tqdev\PhpCrudApi\Database {
|
6103
|
6165
|
case 'sqlsrv':
|
6104
|
6166
|
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"';
|
6105
|
6167
|
case 'sqlite':
|
6106
|
|
- $this->createSqlLiteReflectionTables();
|
|
6168
|
+ $this->updateSqlLiteReflectionTables();
|
6107
|
6169
|
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"';
|
6108
|
6170
|
}
|
6109
|
6171
|
}
|
|
@@ -6118,6 +6180,7 @@ namespace Tqdev\PhpCrudApi\Database {
|
6118
|
6180
|
case 'sqlsrv':
|
6119
|
6181
|
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 \'\' <> ?';
|
6120
|
6182
|
case 'sqlite':
|
|
6183
|
+ $this->updateSqlLiteReflectionTables();
|
6121
|
6184
|
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 \'\' <> ?';
|
6122
|
6185
|
}
|
6123
|
6186
|
}
|