1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Lagdo\DbAdmin\Driver\Sqlite\Db; |
4
|
|
|
|
5
|
|
|
use Lagdo\DbAdmin\Driver\Entity\TableEntity; |
6
|
|
|
|
7
|
|
|
trait DatabaseTrait |
8
|
|
|
{ |
9
|
|
|
private function executeQueries(array $queries): bool |
10
|
|
|
{ |
11
|
|
|
if (!$queries) { |
|
|
|
|
12
|
|
|
return false; |
13
|
|
|
} |
14
|
|
|
$this->driver->execute('BEGIN'); |
15
|
|
|
foreach ($queries as $query) { |
16
|
|
|
if (!$this->driver->execute($query)) { |
17
|
|
|
$this->driver->execute('ROLLBACK'); |
18
|
|
|
return false; |
19
|
|
|
} |
20
|
|
|
} |
21
|
|
|
$this->driver->execute('COMMIT'); |
22
|
|
|
return true; |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @param string $table |
27
|
|
|
* @param int $autoIncrement |
28
|
|
|
* |
29
|
|
|
* @return void |
30
|
|
|
*/ |
31
|
|
|
private function setAutoIncrement(string $table, int $autoIncrement) |
32
|
|
|
{ |
33
|
|
|
if ($autoIncrement) { |
34
|
|
|
$this->driver->execute('BEGIN'); |
35
|
|
|
$this->driver->execute("UPDATE sqlite_sequence SET seq = $autoIncrement WHERE name = " . |
36
|
|
|
$this->driver->quote($table)); // ignores error |
37
|
|
|
if (!$this->driver->affectedRows()) { |
38
|
|
|
$this->driver->execute('INSERT INTO sqlite_sequence (name, seq) VALUES (' . |
39
|
|
|
$this->driver->quote($table) . ", $autoIncrement)"); |
40
|
|
|
} |
41
|
|
|
$this->driver->execute('COMMIT'); |
42
|
|
|
} |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param TableEntity $tableAttrs |
47
|
|
|
* |
48
|
|
|
* @return array |
49
|
|
|
*/ |
50
|
|
|
private function getAlterTableClauses(TableEntity $tableAttrs): array |
51
|
|
|
{ |
52
|
|
|
$clauses = []; |
53
|
|
|
foreach ($tableAttrs->fields as $field) { |
54
|
|
|
if ($field[1]) { |
55
|
|
|
$clauses[] = ($field[0] != '' ? $field[1] : 'ADD ' . implode($field[1])); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
return $clauses; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Recreate a table |
63
|
|
|
* |
64
|
|
|
* @param TableEntity $tableAttrs |
65
|
|
|
* @param string $table |
66
|
|
|
* |
67
|
|
|
* @return bool |
68
|
|
|
*/ |
69
|
|
|
/*private function recreateTable(TableEntity $tableAttrs, string $table = '') |
70
|
|
|
{ |
71
|
|
|
$alter = []; |
72
|
|
|
$originals = []; |
73
|
|
|
foreach ($tableAttrs->fields as $field) { |
74
|
|
|
if ($field[1]) { |
75
|
|
|
$alter[] = (\is_string($field[1]) ? $field[1] : 'ADD ' . implode($field[1])); |
76
|
|
|
if ($field[0] != '') { |
77
|
|
|
$originals[$field[0]] = $field[1][0]; |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
if ($table != '') { |
83
|
|
|
if (empty($tableAttrs->fields)) { |
84
|
|
|
foreach ($this->driver->fields($table) as $key => $field) { |
85
|
|
|
if (!empty($tableAttrs->indexes)) { |
86
|
|
|
$field->autoIncrement = 0; |
87
|
|
|
} |
88
|
|
|
$tableAttrs->fields[] = $this->util->processField($field, $field); |
89
|
|
|
$originals[$key] = $this->driver->escapeId($key); |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
$primary_key = false; |
93
|
|
|
foreach ($tableAttrs->fields as $field) { |
94
|
|
|
if ($field[6]) { |
95
|
|
|
$primary_key = true; |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
$drop_indexes = []; |
99
|
|
|
foreach ($tableAttrs->indexes as $key => $val) { |
100
|
|
|
if ($val[2] == 'DROP') { |
101
|
|
|
$drop_indexes[$val[1]] = true; |
102
|
|
|
unset($tableAttrs->indexes[$key]); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
foreach ($this->driver->indexes($table) as $key_name => $index) { |
106
|
|
|
$columns = []; |
107
|
|
|
foreach ($index->columns as $key => $column) { |
108
|
|
|
if (!$originals[$column]) { |
109
|
|
|
continue 2; |
110
|
|
|
} |
111
|
|
|
$columns[] = $originals[$column] . ($index->descs[$key] ? ' DESC' : ''); |
112
|
|
|
} |
113
|
|
|
if (!$drop_indexes[$key_name]) { |
114
|
|
|
if ($index->type != 'PRIMARY' || !$primary_key) { |
115
|
|
|
$tableAttrs->indexes[] = [$index->type, $key_name, $columns]; |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
foreach ($tableAttrs->indexes as $key => $val) { |
120
|
|
|
if ($val[0] == 'PRIMARY') { |
121
|
|
|
unset($tableAttrs->indexes[$key]); |
122
|
|
|
$foreign[] = ' PRIMARY KEY (' . implode(', ', $val[2]) . ')'; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
foreach ($this->driver->foreignKeys($table) as $key_name => $foreignKey) { |
126
|
|
|
foreach ($foreignKey->source as $key => $column) { |
127
|
|
|
if (!$originals[$column]) { |
128
|
|
|
continue 2; |
129
|
|
|
} |
130
|
|
|
$foreignKey->source[$key] = $this->driver->unescapeId($originals[$column]); |
131
|
|
|
} |
132
|
|
|
if (!isset($foreign[" $key_name"])) { |
133
|
|
|
$foreign[] = ' ' . $this->driver->formatForeignKey($foreignKey); |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
$this->driver->execute('BEGIN'); |
137
|
|
|
} |
138
|
|
|
foreach ($tableAttrs->fields as $key => $field) { |
139
|
|
|
$tableAttrs->fields[$key] = ' ' . implode($field); |
140
|
|
|
} |
141
|
|
|
$tableAttrs->fields = array_merge($tableAttrs->fields, array_filter($tableAttrs->foreign)); |
142
|
|
|
$tempName = ($table == $tableAttrs->name ? "dbadmin_{$tableAttrs->name}" : $tableAttrs->name); |
143
|
|
|
if (!$this->driver->execute('CREATE TABLE ' . $this->driver->table($tempName) . |
144
|
|
|
" (\n" . implode(",\n", $tableAttrs->fields) . "\n)")) { |
145
|
|
|
// implicit ROLLBACK to not overwrite $this->driver->error() |
146
|
|
|
return false; |
147
|
|
|
} |
148
|
|
|
if ($table != '') { |
149
|
|
|
if ($originals && !$this->driver->execute('INSERT INTO ' . $this->driver->table($tempName) . |
150
|
|
|
' (' . implode(', ', $originals) . ') SELECT ' . implode( |
151
|
|
|
', ', |
152
|
|
|
array_map(function ($key) { |
153
|
|
|
return $this->driver->escapeId($key); |
154
|
|
|
}, array_keys($originals)) |
155
|
|
|
) . ' FROM ' . $this->driver->table($table))) { |
156
|
|
|
return false; |
157
|
|
|
} |
158
|
|
|
$triggers = []; |
159
|
|
|
foreach ($this->driver->triggers($table) as $trigger_name => $timing_event) { |
160
|
|
|
$trigger = $this->driver->trigger($trigger_name); |
161
|
|
|
$triggers[] = 'CREATE TRIGGER ' . $this->driver->escapeId($trigger_name) . ' ' . |
162
|
|
|
implode(' ', $timing_event) . ' ON ' . $this->driver->table($tableAttrs->name) . "\n$trigger[Statement]"; |
163
|
|
|
} |
164
|
|
|
$autoIncrement = $tableAttrs->autoIncrement ? 0 : |
165
|
|
|
$this->driver->result('SELECT seq FROM sqlite_sequence WHERE name = ' . |
166
|
|
|
$this->driver->quote($table)); // if $autoIncrement is set then it will be updated later |
167
|
|
|
// Drop before creating indexes and triggers to allow using old names |
168
|
|
|
if (!$this->driver->execute('DROP TABLE ' . $this->driver->table($table)) || |
169
|
|
|
($table == $tableAttrs->name && !$this->driver->execute('ALTER TABLE ' . $this->driver->table($tempName) . |
170
|
|
|
' RENAME TO ' . $this->driver->table($tableAttrs->name))) || !$this->alterIndexes($tableAttrs->name, $tableAttrs->indexes) |
171
|
|
|
) { |
172
|
|
|
return false; |
173
|
|
|
} |
174
|
|
|
if ($autoIncrement) { |
175
|
|
|
$this->driver->execute('UPDATE sqlite_sequence SET seq = $autoIncrement WHERE name = ' . |
176
|
|
|
$this->driver->quote($tableAttrs->name)); // ignores error |
177
|
|
|
} |
178
|
|
|
foreach ($triggers as $trigger) { |
179
|
|
|
if (!$this->driver->execute($trigger)) { |
180
|
|
|
return false; |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
$this->driver->execute('COMMIT'); |
184
|
|
|
} |
185
|
|
|
return true; |
186
|
|
|
}*/ |
187
|
|
|
} |
188
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.