This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * @link http://www.yiiframework.com/ |
||
5 | * @copyright Copyright (c) 2008 Yii Software LLC |
||
6 | * @license http://www.yiiframework.com/license/ |
||
7 | */ |
||
8 | |||
9 | namespace edgardmessias\db\ibm\db2; |
||
10 | |||
11 | use PDO; |
||
12 | use yii\db\Expression; |
||
13 | use yii\db\TableSchema; |
||
14 | use yii\db\Transaction; |
||
15 | |||
16 | /** |
||
17 | * @author Edgard Messias <[email protected]> |
||
18 | * @author Nikita Verkhovin <[email protected]> |
||
19 | * @since 1.0 |
||
20 | */ |
||
21 | |||
22 | class Schema extends \yii\db\Schema implements \yii\db\ConstraintFinderInterface |
||
23 | { |
||
24 | use \yii\db\ViewFinderTrait; |
||
25 | use \yii\db\ConstraintFinderTrait; |
||
26 | |||
27 | public $typeMap = [ |
||
28 | 'character' => self::TYPE_CHAR, |
||
29 | 'varchar' => self::TYPE_STRING, |
||
30 | 'char' => self::TYPE_CHAR, |
||
31 | 'clob' => self::TYPE_TEXT, |
||
32 | 'graphic' => self::TYPE_STRING, |
||
33 | 'vargraphic' => self::TYPE_STRING, |
||
34 | 'varg' => self::TYPE_STRING, |
||
35 | 'dbclob' => self::TYPE_TEXT, |
||
36 | 'nchar' => self::TYPE_CHAR, |
||
37 | 'nvarchar' => self::TYPE_STRING, |
||
38 | 'nclob' => self::TYPE_TEXT, |
||
39 | 'binary' => self::TYPE_BINARY, |
||
40 | 'varbinary' => self::TYPE_BINARY, |
||
41 | 'varbin' => self::TYPE_BINARY, |
||
42 | 'blob' => self::TYPE_BINARY, |
||
43 | 'smallint' => self::TYPE_SMALLINT, |
||
44 | 'int' => self::TYPE_INTEGER, |
||
45 | 'integer' => self::TYPE_INTEGER, |
||
46 | 'bigint' => self::TYPE_BIGINT, |
||
47 | 'decimal' => self::TYPE_DECIMAL, |
||
48 | 'numeric' => self::TYPE_DECIMAL, |
||
49 | 'real' => self::TYPE_FLOAT, |
||
50 | 'float' => self::TYPE_FLOAT, |
||
51 | 'double' => self::TYPE_DOUBLE, |
||
52 | 'decfloat' => self::TYPE_FLOAT, |
||
53 | 'date' => self::TYPE_DATE, |
||
54 | 'time' => self::TYPE_TIME, |
||
55 | 'timestamp' => self::TYPE_TIMESTAMP, |
||
56 | 'timestmp' => self::TYPE_TIMESTAMP |
||
57 | ]; |
||
58 | |||
59 | /** |
||
60 | * @inheritdoc |
||
61 | */ |
||
62 | 181 | public function createQueryBuilder() |
|
63 | { |
||
64 | 181 | return new QueryBuilder($this->db); |
|
65 | } |
||
66 | |||
67 | /** |
||
68 | * @inheritdoc |
||
69 | */ |
||
70 | 268 | public function quoteSimpleTableName($name) |
|
71 | { |
||
72 | 268 | return strpos($name, '"') !== false ? $name : '"' . $name . '"'; |
|
73 | } |
||
74 | |||
75 | /** |
||
76 | * @inheritdoc |
||
77 | */ |
||
78 | 295 | public function quoteSimpleColumnName($name) |
|
79 | { |
||
80 | 295 | return strpos($name, '"') !== false || $name === '*' ? $name : '"' . $name . '"'; |
|
81 | } |
||
82 | |||
83 | /** |
||
84 | * @inheritdoc |
||
85 | */ |
||
86 | 196 | protected function loadTableSchema($name) |
|
87 | { |
||
88 | 196 | $table = new TableSchema(); |
|
89 | 196 | $this->resolveTableNames($table, $name); |
|
90 | |||
91 | 196 | if ($this->findColumns($table)) { |
|
92 | 189 | $this->findConstraints($table); |
|
93 | 189 | return $table; |
|
94 | } else { |
||
95 | 14 | return null; |
|
96 | } |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * @inheritdoc |
||
101 | */ |
||
102 | 256 | protected function resolveTableNames($table, $name) |
|
103 | { |
||
104 | 256 | $parts = explode('.', str_replace('"', '', $name)); |
|
105 | 256 | if (isset($parts[1])) { |
|
106 | $table->schemaName = $parts[0]; |
||
107 | $table->name = $parts[1]; |
||
108 | $table->fullName = $table->schemaName . '.' . $table->name; |
||
109 | } else { |
||
110 | 256 | $table->fullName = $table->name = $parts[0]; |
|
111 | } |
||
112 | 256 | } |
|
113 | |||
114 | /** |
||
115 | * {@inheritdoc} |
||
116 | */ |
||
117 | 83 | protected function resolveTableName($name) |
|
118 | { |
||
119 | 83 | $resolvedName = new TableSchema(); |
|
120 | 83 | $this->resolveTableNames($resolvedName, $name); |
|
121 | 83 | return $resolvedName; |
|
122 | } |
||
123 | |||
124 | /** |
||
125 | * Determines the PDO type for the given PHP data value. |
||
126 | * @param mixed $data the data whose PDO type is to be determined |
||
127 | * @return integer the PDO type |
||
128 | * @see http://www.php.net/manual/en/pdo.constants.php |
||
129 | */ |
||
130 | 283 | public function getPdoType($data) |
|
131 | { |
||
132 | static $typeMap = [ |
||
133 | // php type => PDO type |
||
134 | 'boolean' => PDO::PARAM_INT, // PARAM_BOOL is not supported by DB2 PDO |
||
135 | 'integer' => PDO::PARAM_INT, |
||
136 | 'string' => PDO::PARAM_STR, |
||
137 | 'resource' => PDO::PARAM_LOB, |
||
138 | 'NULL' => PDO::PARAM_INT, // PDO IBM doesn't support PARAM_NULL |
||
139 | 283 | ]; |
|
140 | 283 | $type = gettype($data); |
|
141 | |||
142 | 283 | return isset($typeMap[$type]) ? $typeMap[$type] : PDO::PARAM_STR; |
|
143 | } |
||
144 | |||
145 | /** |
||
146 | * @inheritdoc |
||
147 | */ |
||
148 | 189 | protected function loadColumnSchema($info) |
|
149 | { |
||
150 | 189 | $column = $this->createColumnSchema(); |
|
151 | |||
152 | 189 | $column->name = $info['name']; |
|
153 | 189 | $column->dbType = $info['dbtype']; |
|
154 | 189 | $column->defaultValue = isset($info['defaultvalue']) ? trim($info['defaultvalue'], "''") : null; |
|
155 | 189 | $column->scale = (int) $info['scale']; |
|
156 | 189 | $column->size = (int) $info['size']; |
|
157 | 189 | $column->precision = (int) $info['size']; |
|
158 | 189 | $column->allowNull = $info['allownull'] === '1'; |
|
159 | 189 | $column->isPrimaryKey = $info['isprimarykey'] === '1'; |
|
160 | 189 | $column->autoIncrement = $info['autoincrement'] === '1'; |
|
161 | 189 | $column->unsigned = false; |
|
162 | 189 | $column->type = $this->typeMap[strtolower($info['dbtype'])]; |
|
163 | 189 | $column->enumValues = null; |
|
0 ignored issues
–
show
|
|||
164 | 189 | $column->comment = isset($info['comment']) ? $info['comment'] : null; |
|
165 | |||
166 | 189 | if (preg_match('/(varchar|character|clob|graphic|binary|blob)/i', $info['dbtype'])) { |
|
167 | 165 | $column->dbType .= '(' . $info['size'] . ')'; |
|
168 | 189 | } elseif (preg_match('/(decimal|double|real)/i', $info['dbtype'])) { |
|
169 | 84 | $column->dbType .= '(' . $info['size'] . ',' . $info['scale'] . ')'; |
|
170 | 84 | } |
|
171 | |||
172 | 189 | if ($column->defaultValue) { |
|
0 ignored issues
–
show
The expression
$column->defaultValue of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
173 | 28 | if ($column->type === 'timestamp' && $column->defaultValue === 'CURRENT TIMESTAMP') { |
|
174 | 23 | $column->defaultValue = new Expression($column->defaultValue); |
|
175 | 23 | } |
|
176 | 28 | } |
|
177 | |||
178 | 189 | $column->phpType = $this->getColumnPhpType($column); |
|
179 | |||
180 | 189 | return $column; |
|
181 | } |
||
182 | |||
183 | /** |
||
184 | * @inheritdoc |
||
185 | */ |
||
186 | 196 | protected function findColumns($table) |
|
187 | { |
||
188 | |||
189 | |||
190 | 196 | if ($this->db->isISeries) { |
|
191 | $sql = <<<SQL |
||
192 | SELECT c.column_name AS name, |
||
193 | c.data_type AS dbtype, |
||
194 | CAST(c.column_default AS VARCHAR(254)) AS defaultvalue, |
||
195 | CASE WHEN c.is_nullable = 'Y' THEN 1 ELSE 0 END AS allownull, |
||
196 | c.length AS size, |
||
197 | c.numeric_scale AS scale, |
||
198 | CASE WHEN c.is_identity = 'YES' THEN 1 ELSE 0 END AS autoincrement, |
||
199 | case when x.column<>'' THEN 1 ELSE 0 END AS isprimarykey |
||
200 | FROM qsys2.syscolumns c |
||
201 | left join ( |
||
202 | SELECT |
||
203 | column_name As column |
||
204 | FROM qsys2.syscst |
||
205 | INNER JOIN qsys2.syskeycst |
||
206 | ON qsys2.syscst.constraint_name = qsys2.syskeycst.constraint_name |
||
207 | AND qsys2.syscst.table_schema = qsys2.syskeycst.table_schema |
||
208 | AND qsys2.syscst.table_name = qsys2.syskeycst.table_name |
||
209 | WHERE qsys2.syscst.constraint_type = 'PRIMARY KEY' |
||
210 | AND qsys2.syscst.table_name = :table) x |
||
211 | on x.column= c.column_name |
||
212 | WHERE UPPER(c.table_name) = :table1 |
||
213 | AND c.table_schema = :schema |
||
214 | SQL; |
||
215 | $sql .= ' ORDER BY c.ordinal_position'; |
||
216 | } else { |
||
217 | $sql = <<<SQL |
||
218 | SELECT |
||
219 | c.colname AS name, |
||
220 | c.typename AS dbtype, |
||
221 | cast(c.default as varchar(254)) AS defaultvalue, |
||
222 | c.scale AS scale, |
||
223 | c.length AS size, |
||
224 | CASE WHEN c.nulls = 'Y' THEN 1 ELSE 0 END AS allownull, |
||
225 | CASE WHEN c.keyseq IS NOT NULL THEN 1 ELSE 0 END AS isprimarykey, |
||
226 | CASE WHEN c.identity = 'Y' THEN 1 ELSE 0 END AS autoincrement, |
||
227 | c.remarks AS comment |
||
228 | FROM |
||
229 | syscat.columns AS c |
||
230 | WHERE |
||
231 | c.tabname = :table |
||
232 | 196 | SQL; |
|
233 | |||
234 | 196 | if (isset($table->schemaName)) { |
|
235 | $sql .= ' AND c.tabschema = :schema'; |
||
236 | } |
||
237 | |||
238 | 196 | $sql .= ' ORDER BY c.colno'; |
|
239 | } |
||
240 | |||
241 | 196 | $command = $this->db->createCommand($sql); |
|
242 | 196 | $command->bindValue(':table', $table->name); |
|
243 | 196 | if($this->db->isISeries){ |
|
244 | $command->bindValue(':schema', $this->db->defaultSchema); |
||
0 ignored issues
–
show
The property
defaultSchema does not seem to exist. Did you mean schema ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
245 | $command->bindValue(':table1', $table->name); |
||
246 | |||
247 | }else { |
||
248 | 196 | if (isset($table->schemaName)) { |
|
249 | $command->bindValue(':schema', $table->schemaName); |
||
250 | } |
||
251 | } |
||
252 | 196 | $columns = $command->queryAll(); |
|
253 | 196 | if (empty($columns)) { |
|
254 | 14 | return false; |
|
255 | } |
||
256 | |||
257 | 189 | $columns = $this->normalizePdoRowKeyCase($columns, true); |
|
258 | |||
259 | 189 | foreach ($columns as $info) { |
|
260 | 189 | $column = $this->loadColumnSchema($info); |
|
261 | 189 | $table->columns[$column->name] = $column; |
|
262 | 189 | if ($column->isPrimaryKey) { |
|
263 | 164 | $table->primaryKey[] = $column->name; |
|
264 | 164 | if ($column->autoIncrement) { |
|
265 | 161 | $table->sequenceName = $column->name; |
|
266 | 161 | } |
|
267 | 164 | } |
|
268 | 189 | } |
|
269 | 189 | return true; |
|
270 | } |
||
271 | |||
272 | /** |
||
273 | * @inheritdoc |
||
274 | */ |
||
275 | 189 | protected function findConstraints($table) |
|
276 | { |
||
277 | 189 | if ($this->db->isISeries) { |
|
278 | $sql = <<<SQL |
||
279 | SELECT |
||
280 | child.constraint_name as name, |
||
281 | parent.table_name AS tablename, |
||
282 | parent.column_name AS pk, |
||
283 | child.column_name AS fk |
||
284 | FROM qsys2.syskeycst child |
||
285 | INNER JOIN qsys2.sysrefcst crossref |
||
286 | ON child.constraint_schema = crossref.constraint_schema |
||
287 | AND child.constraint_name = crossref.constraint_name |
||
288 | INNER JOIN qsys2.syskeycst parent |
||
289 | ON crossref.unique_constraint_schema = parent.constraint_schema |
||
290 | AND crossref.unique_constraint_name = parent.constraint_name |
||
291 | INNER JOIN qsys2.syscst coninfo |
||
292 | ON child.constraint_name = coninfo.constraint_name |
||
293 | WHERE UPPER(child.table_name) = :table |
||
294 | AND coninfo.constraint_type = 'FOREIGN KEY' |
||
295 | AND child.table_schema = :schema |
||
296 | SQL; |
||
297 | |||
298 | } else { |
||
299 | $sql = <<<SQL |
||
300 | SELECT |
||
301 | fk.constname as name, |
||
302 | pk.tabname AS tablename, |
||
303 | fk.colname AS fk, |
||
304 | pk.colname AS pk |
||
305 | FROM |
||
306 | syscat.references AS ref |
||
307 | INNER JOIN |
||
308 | syscat.keycoluse AS fk ON ref.constname = fk.constname |
||
309 | INNER JOIN |
||
310 | syscat.keycoluse AS pk ON ref.refkeyname = pk.constname AND pk.colseq = fk.colseq |
||
311 | WHERE |
||
312 | fk.tabname = :table |
||
313 | 189 | SQL; |
|
314 | |||
315 | 189 | if (isset($table->schemaName)) { |
|
316 | $sql .= ' AND fk.tabschema = :schema'; |
||
317 | } |
||
318 | } |
||
319 | 189 | $command = $this->db->createCommand($sql); |
|
320 | 189 | $command->bindValue(':table', $table->name); |
|
321 | 189 | if($this->db->isISeries){ |
|
322 | $command->bindValue(':schema', $this->db->defaultSchema); |
||
0 ignored issues
–
show
The property
defaultSchema does not seem to exist. Did you mean schema ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
323 | }else { |
||
324 | 189 | if (isset($table->schemaName)) { |
|
325 | $command->bindValue(':schema', $table->schemaName); |
||
326 | } |
||
327 | } |
||
328 | |||
329 | 189 | $constraints = $command->queryAll(); |
|
330 | 189 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
331 | |||
332 | 189 | $constraints = \yii\helpers\ArrayHelper::index($constraints, null, ['name']); |
|
333 | |||
334 | 189 | foreach ($constraints as $name => $constraint) { |
|
335 | 66 | $fks = \yii\helpers\ArrayHelper::getColumn($constraint, 'fk'); |
|
336 | 66 | $pks = \yii\helpers\ArrayHelper::getColumn($constraint, 'pk'); |
|
337 | |||
338 | 66 | $tablename = $constraint[0]['tablename']; |
|
339 | |||
340 | 66 | $keymap = array_combine($fks, $pks); |
|
341 | |||
342 | 66 | $foreignKeys = [$tablename]; |
|
343 | 66 | foreach ($keymap as $fk => $pk) { |
|
344 | 66 | $foreignKeys[$fk] = $pk; |
|
345 | 66 | } |
|
346 | |||
347 | 66 | $table->foreignKeys[$name] = $foreignKeys; |
|
348 | 189 | } |
|
349 | 189 | } |
|
350 | |||
351 | /** |
||
352 | * @inheritdoc |
||
353 | */ |
||
354 | 1 | public function findUniqueIndexes($table) |
|
355 | { |
||
356 | |||
357 | 1 | if ($this->db->isISeries) { |
|
358 | $sql = <<<SQL |
||
359 | SELECT |
||
360 | qsys2.syskeycst.constraint_name As indexname, |
||
361 | qsys2.syskeycst.column_name As column |
||
362 | FROM qsys2.syscst |
||
363 | INNER JOIN qsys2.syskeycst |
||
364 | ON qsys2.syscst.constraint_name = qsys2.syskeycst.constraint_name |
||
365 | AND qsys2.syscst.table_schema = qsys2.syskeycst.table_schema |
||
366 | AND qsys2.syscst.table_name = qsys2.syskeycst.table_name |
||
367 | WHERE qsys2.syscst.constraint_type = 'PRIMARY KEY' |
||
368 | AND qsys2.syscst.table_name = :table |
||
369 | AND qsys2.syscst.table_schema = :schema |
||
370 | ORDER BY qsys2.syskeycst.column_position |
||
371 | SQL; |
||
372 | }else { |
||
373 | $sql = <<<SQL |
||
374 | SELECT |
||
375 | i.indname AS indexname, |
||
376 | ic.colname AS column |
||
377 | FROM |
||
378 | syscat.indexes AS i |
||
379 | INNER JOIN |
||
380 | syscat.indexcoluse AS ic ON i.indname = ic.indname |
||
381 | WHERE |
||
382 | i.tabname = :table |
||
383 | 1 | SQL; |
|
384 | |||
385 | 1 | if (isset($table->schemaName)) { |
|
386 | $sql .= ' AND tabschema = :schema'; |
||
387 | } |
||
388 | |||
389 | 1 | $sql .= ' ORDER BY ic.colseq'; |
|
390 | } |
||
391 | 1 | $command = $this->db->createCommand($sql); |
|
392 | 1 | $command->bindValue(':table', $table->name); |
|
393 | |||
394 | 1 | if($this->db->isISeries){ |
|
395 | $command->bindValue(':schema', $this->db->defaultSchema); |
||
0 ignored issues
–
show
The property
defaultSchema does not seem to exist. Did you mean schema ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
396 | }else{ |
||
397 | 1 | if (isset($table->schemaName)) { |
|
398 | $command->bindValue(':schema', $table->schemaName); |
||
399 | } |
||
400 | } |
||
401 | 1 | $results = $command->queryAll(); |
|
402 | 1 | $results = $this->normalizePdoRowKeyCase($results, true); |
|
403 | |||
404 | 1 | $indexes = []; |
|
405 | 1 | foreach ($results as $result) { |
|
406 | 1 | $indexes[$result['indexname']][] = $result['column']; |
|
407 | 1 | } |
|
408 | 1 | return $indexes; |
|
409 | } |
||
410 | |||
411 | /** |
||
412 | * @inheritdoc |
||
413 | */ |
||
414 | 5 | protected function findTableNames($schema = '') |
|
415 | { |
||
416 | |||
417 | 5 | if ($schema === '' && $this->db->isISeries) { |
|
418 | $schema= $this->db->defaultSchema; |
||
0 ignored issues
–
show
The property
defaultSchema does not seem to exist. Did you mean schema ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
419 | } |
||
420 | |||
421 | 5 | if ($this->db->isISeries) { |
|
422 | $sql = <<<SQL |
||
423 | SELECT TABLE_NAME as tabname |
||
424 | FROM QSYS2.SYSTABLES |
||
425 | WHERE TABLE_TYPE IN ('P','T','V') |
||
426 | AND SYSTEM_TABLE = 'N' |
||
427 | AND TABLE_SCHEMA = :schema |
||
428 | ORDER BY TABLE_NAME |
||
429 | SQL; |
||
430 | }else { |
||
431 | |||
432 | $sql = <<<SQL |
||
433 | SELECT |
||
434 | t.tabname |
||
435 | FROM |
||
436 | syscat.tables AS t |
||
437 | WHERE |
||
438 | t.type in ('P','T', 'V') AND |
||
439 | t.ownertype != 'S' |
||
440 | 5 | SQL; |
|
441 | |||
442 | 5 | if ($schema !== '') { |
|
443 | $sql .= ' AND t.tabschema = :schema'; |
||
444 | } |
||
445 | } |
||
446 | 5 | $command = $this->db->createCommand($sql); |
|
447 | |||
448 | 5 | if ($schema !== '') { |
|
449 | $command->bindValue(':schema', $schema); |
||
450 | } |
||
451 | |||
452 | 5 | return $command->queryColumn(); |
|
453 | } |
||
454 | |||
455 | /** |
||
456 | * @inheritdoc |
||
457 | */ |
||
458 | 1 | protected function findSchemaNames() |
|
459 | { |
||
460 | |||
461 | $sql = <<<SQL |
||
462 | SELECT |
||
463 | t.schemaname |
||
464 | FROM |
||
465 | syscat.schemata AS t |
||
466 | WHERE |
||
467 | t.definertype != 'S' AND |
||
468 | t.definer != 'DB2INST1' |
||
469 | 1 | SQL; |
|
470 | |||
471 | 1 | $command = $this->db->createCommand($sql); |
|
472 | |||
473 | 1 | $schemas = $command->queryColumn(); |
|
474 | |||
475 | 1 | return array_map('trim', $schemas); |
|
476 | } |
||
477 | |||
478 | /** |
||
479 | * Creates a new savepoint. |
||
480 | * @param string $name the savepoint name |
||
481 | */ |
||
482 | 1 | public function createSavepoint($name) |
|
483 | { |
||
484 | 1 | $this->db->createCommand("SAVEPOINT $name ON ROLLBACK RETAIN CURSORS")->execute(); |
|
485 | 1 | } |
|
486 | |||
487 | /** |
||
488 | * Sets the isolation level of the current transaction. |
||
489 | * @param string $level The transaction isolation level to use for this transaction. |
||
490 | * This can be one of [[Transaction::READ_UNCOMMITTED]], [[Transaction::READ_COMMITTED]], [[Transaction::REPEATABLE_READ]] |
||
491 | * and [[Transaction::SERIALIZABLE]] but also a string containing DBMS specific syntax to be used |
||
492 | * after `SET TRANSACTION ISOLATION LEVEL`. |
||
493 | * @see http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Isolation_levels |
||
494 | */ |
||
495 | 2 | public function setTransactionIsolationLevel($level) |
|
496 | { |
||
497 | 2 | $sql = 'SET CURRENT ISOLATION '; |
|
498 | switch ($level) { |
||
499 | 2 | case Transaction::READ_UNCOMMITTED: |
|
500 | 2 | $sql .= 'UR'; |
|
501 | 2 | break; |
|
502 | 1 | case Transaction::READ_COMMITTED: |
|
503 | 1 | $sql .= 'CS'; |
|
504 | 1 | break; |
|
505 | 1 | case Transaction::REPEATABLE_READ: |
|
506 | 1 | $sql .= 'RS'; |
|
507 | 1 | break; |
|
508 | 1 | case Transaction::SERIALIZABLE: |
|
509 | 1 | $sql .= 'RR'; |
|
510 | 1 | break; |
|
511 | default: |
||
512 | $sql .= $level; |
||
513 | } |
||
514 | |||
515 | 2 | $this->db->createCommand($sql)->execute(); |
|
516 | 2 | } |
|
517 | |||
518 | /** |
||
519 | * Refreshes the particular table schema. |
||
520 | * This method cleans up cached table schema so that it can be re-created later |
||
521 | * to reflect the database schema change. |
||
522 | * @param string $name table name. |
||
523 | * @since 2.0.6 |
||
524 | */ |
||
525 | 22 | public function refreshTableSchema($name) |
|
526 | { |
||
527 | 22 | if ($name) { |
|
528 | try { |
||
529 | 22 | $sql = "CALL ADMIN_CMD ('REORG TABLE " . $this->db->quoteTableName($name) . "')"; |
|
530 | 22 | $this->db->createCommand($sql)->execute(); |
|
531 | 22 | } catch (\Exception $ex) { |
|
532 | // Do not throw error on table which doesn't exist (-2211) |
||
533 | // Do not throw error on view (-2212) |
||
534 | 7 | $code = isset($ex->errorInfo[1]) ? $ex->errorInfo[1] : 0; |
|
0 ignored issues
–
show
The property
errorInfo does not seem to exist in Exception .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
535 | 7 | if (!in_array($code, [-2211, -2212])) { |
|
536 | throw new \Exception($ex->getMessage(), $ex->getCode(), $ex->getPrevious()); |
||
537 | } |
||
538 | } |
||
539 | 22 | } |
|
540 | |||
541 | 22 | parent::refreshTableSchema($name); |
|
542 | 22 | } |
|
543 | |||
544 | protected function findViewNames($schema = '') { |
||
545 | $sql = <<<SQL |
||
546 | SELECT t.viewname |
||
547 | FROM syscat.views AS t |
||
548 | WHERE t.ownertype != 'S' |
||
549 | SQL; |
||
550 | |||
551 | if ($schema !== '') { |
||
552 | $sql .= ' AND t.viewschema = :schema'; |
||
553 | } |
||
554 | $command = $this->db->createCommand($sql); |
||
555 | |||
556 | if ($schema !== '') { |
||
557 | $command->bindValue(':schema', $schema); |
||
558 | } |
||
559 | |||
560 | return $command->queryColumn(); |
||
561 | } |
||
562 | |||
563 | 30 | protected function loadTablePrimaryKey($tableName) { |
|
564 | 30 | $resolvedName = $this->resolveTableName($tableName); |
|
565 | |||
566 | $sql = <<<SQL |
||
567 | SELECT CASE |
||
568 | WHEN i.indschema = 'SYSIBM' THEN NULL |
||
569 | ELSE i.indname |
||
570 | END AS name, |
||
571 | t.colname AS column_name |
||
572 | FROM syscat.columns AS t |
||
573 | LEFT JOIN syscat.indexes AS i |
||
574 | ON i.tabschema = t.tabschema |
||
575 | AND i.tabname = t.tabname |
||
576 | INNER JOIN syscat.indexcoluse AS ic |
||
577 | ON ic.indschema = i.indschema |
||
578 | AND ic.indname = i.indname |
||
579 | AND ic.colname = t.colname |
||
580 | WHERE t.keyseq IS NOT NULL |
||
581 | AND i.ownertype != 'S' |
||
582 | AND t.tabname = :table |
||
583 | 30 | SQL; |
|
584 | |||
585 | 30 | if ($resolvedName->sequenceName) { |
|
586 | $sql .= ' AND t.tabschema = :schema'; |
||
587 | } |
||
588 | |||
589 | 30 | $sql .= ' ORDER BY t.keyseq'; |
|
590 | |||
591 | 30 | $command = $this->db->createCommand($sql); |
|
592 | |||
593 | 30 | $command->bindValue(':table', $resolvedName->name); |
|
594 | |||
595 | 30 | if ($resolvedName->sequenceName) { |
|
596 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
597 | } |
||
598 | |||
599 | 30 | $constraints = $command->queryAll(); |
|
600 | |||
601 | 30 | if (empty($constraints)) { |
|
602 | 4 | return null; |
|
603 | } |
||
604 | |||
605 | 27 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
606 | |||
607 | 27 | $columns = \yii\helpers\ArrayHelper::getColumn($constraints, 'column_name'); |
|
608 | |||
609 | 27 | return new \yii\db\Constraint([ |
|
610 | 27 | 'name' => $constraints[0]['name'], |
|
611 | 27 | 'columnNames' => $columns, |
|
612 | 27 | ]); |
|
613 | } |
||
614 | |||
615 | 30 | protected function loadTableUniques($tableName) { |
|
616 | 30 | $resolvedName = $this->resolveTableName($tableName); |
|
617 | |||
618 | $sql = <<<SQL |
||
619 | SELECT i.indname AS name, |
||
620 | ic.colname AS column_name |
||
621 | FROM syscat.indexes AS i |
||
622 | INNER JOIN syscat.indexcoluse AS ic |
||
623 | ON ic.indschema = i.indschema |
||
624 | AND ic.indname = i.indname |
||
625 | WHERE i.ownertype != 'S' |
||
626 | AND i.indschema != 'SYSIBM' |
||
627 | AND i.uniquerule = 'U' |
||
628 | AND i.tabname = :table |
||
629 | 30 | SQL; |
|
630 | |||
631 | 30 | if ($resolvedName->sequenceName) { |
|
632 | $sql .= ' AND i.tabschema = :schema'; |
||
633 | } |
||
634 | |||
635 | 30 | $sql .= ' ORDER BY ic.colseq'; |
|
636 | |||
637 | 30 | $command = $this->db->createCommand($sql); |
|
638 | |||
639 | 30 | $command->bindValue(':table', $resolvedName->name); |
|
640 | |||
641 | 30 | if ($resolvedName->sequenceName) { |
|
642 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
643 | } |
||
644 | |||
645 | 30 | $constraints = $command->queryAll(); |
|
646 | 30 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
647 | 30 | $constraints = \yii\helpers\ArrayHelper::index($constraints, null, ['name']); |
|
648 | 30 | $result = []; |
|
649 | 30 | foreach ($constraints as $name => $constraint) { |
|
650 | 10 | $columns = \yii\helpers\ArrayHelper::getColumn($constraint, 'column_name'); |
|
651 | |||
652 | 10 | $result[] = new \yii\db\Constraint([ |
|
653 | 10 | 'name' => $name, |
|
654 | 10 | 'columnNames' => $columns, |
|
655 | 10 | ]); |
|
656 | 30 | } |
|
657 | 30 | return $result; |
|
658 | } |
||
659 | |||
660 | 13 | protected function loadTableChecks($tableName) { |
|
661 | 13 | $resolvedName = $this->resolveTableName($tableName); |
|
662 | |||
663 | $sql = <<<SQL |
||
664 | SELECT c.constname AS name, |
||
665 | cc.colname AS column_name, |
||
666 | c.text AS check_expr |
||
667 | FROM syscat.checks AS c |
||
668 | INNER JOIN syscat.colchecks cc |
||
669 | ON cc.constname = c.constname |
||
670 | WHERE c.ownertype != 'S' |
||
671 | AND c.tabname = :table |
||
672 | 13 | SQL; |
|
673 | |||
674 | 13 | if ($resolvedName->sequenceName) { |
|
675 | $sql .= ' AND c.tabschema = :schema'; |
||
676 | } |
||
677 | |||
678 | 13 | $command = $this->db->createCommand($sql); |
|
679 | |||
680 | 13 | $command->bindValue(':table', $resolvedName->name); |
|
681 | |||
682 | 13 | if ($resolvedName->sequenceName) { |
|
683 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
684 | } |
||
685 | |||
686 | 13 | $constraints = $command->queryAll(); |
|
687 | 13 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
688 | 13 | $constraints = \yii\helpers\ArrayHelper::index($constraints, null, ['name']); |
|
689 | 13 | $result = []; |
|
690 | 13 | foreach ($constraints as $name => $constraint) { |
|
691 | 4 | $columns = \yii\helpers\ArrayHelper::getColumn($constraint, 'column_name'); |
|
692 | 4 | $check_expr = $constraint[0]['check_expr']; |
|
693 | 4 | $result[] = new \yii\db\CheckConstraint([ |
|
694 | 4 | 'name' => strtolower(trim($name)), |
|
695 | 4 | 'columnNames' => $columns, |
|
696 | 4 | 'expression' => $check_expr, |
|
697 | 4 | ]); |
|
698 | 13 | } |
|
699 | 13 | return $result; |
|
700 | } |
||
701 | |||
702 | 13 | protected function loadTableDefaultValues($tableName) { |
|
703 | 13 | $resolvedName = $this->resolveTableName($tableName); |
|
704 | |||
705 | $sql = <<<SQL |
||
706 | SELECT c.colname AS column_name, |
||
707 | c.default AS default_value |
||
708 | FROM syscat.columns AS c |
||
709 | WHERE c.default IS NOT NULL |
||
710 | AND c.tabname = :table |
||
711 | 13 | SQL; |
|
712 | |||
713 | 13 | if ($resolvedName->sequenceName) { |
|
714 | $sql .= ' AND c.tabschema = :schema'; |
||
715 | } |
||
716 | |||
717 | 13 | $sql .= ' ORDER BY c.colno'; |
|
718 | |||
719 | 13 | $command = $this->db->createCommand($sql); |
|
720 | |||
721 | 13 | $command->bindValue(':table', $resolvedName->name); |
|
722 | |||
723 | 13 | if ($resolvedName->sequenceName) { |
|
724 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
725 | } |
||
726 | |||
727 | 13 | $constraints = $command->queryAll(); |
|
728 | 13 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
729 | |||
730 | 13 | $result = []; |
|
731 | 13 | foreach ($constraints as $constraint) { |
|
732 | 10 | $columns = [$constraint['column_name']]; |
|
733 | 10 | $default_value = $constraint['default_value']; |
|
734 | 10 | $result[] = new \yii\db\DefaultValueConstraint([ |
|
735 | 10 | 'columnNames' => $columns, |
|
736 | 10 | 'value' => $default_value, |
|
737 | 10 | ]); |
|
738 | 13 | } |
|
739 | 13 | return $result; |
|
740 | } |
||
741 | |||
742 | 4 | protected function loadTableForeignKeys($tableName) { |
|
743 | 4 | $resolvedName = $this->resolveTableName($tableName); |
|
744 | |||
745 | $sql = <<<SQL |
||
746 | SELECT ref.constname AS name, |
||
747 | fk.colname AS column_name, |
||
748 | ref.reftabschema AS ref_schema, |
||
749 | ref.reftabname AS ref_table, |
||
750 | pk.colname AS ref_column, |
||
751 | ref.deleterule AS on_delete, |
||
752 | ref.updaterule AS on_update |
||
753 | FROM syscat.references AS ref |
||
754 | INNER JOIN syscat.keycoluse AS fk |
||
755 | ON ref.constname = fk.constname |
||
756 | INNER JOIN syscat.keycoluse AS pk |
||
757 | ON ref.refkeyname = pk.constname |
||
758 | AND pk.colseq = fk.colseq |
||
759 | WHERE ref.tabname = :table |
||
760 | 4 | SQL; |
|
761 | |||
762 | 4 | if ($resolvedName->sequenceName) { |
|
763 | $sql .= ' AND ref.tabschema = :schema'; |
||
764 | } |
||
765 | |||
766 | 4 | $sql .= ' ORDER BY fk.colseq'; |
|
767 | |||
768 | 4 | $command = $this->db->createCommand($sql); |
|
769 | |||
770 | 4 | $command->bindValue(':table', $resolvedName->name); |
|
771 | |||
772 | 4 | if ($resolvedName->sequenceName) { |
|
773 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
774 | } |
||
775 | |||
776 | 4 | $constraints = $command->queryAll(); |
|
777 | 4 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
778 | 4 | $constraints = \yii\helpers\ArrayHelper::index($constraints, null, ['name']); |
|
779 | 4 | $result = []; |
|
780 | 4 | foreach ($constraints as $name => $constraint) { |
|
781 | 4 | $columns = \yii\helpers\ArrayHelper::getColumn($constraint, 'column_name'); |
|
782 | 4 | $foreignColumnNames = \yii\helpers\ArrayHelper::getColumn($constraint, 'ref_column'); |
|
783 | |||
784 | 4 | $foreignSchemaName = $constraint[0]['ref_schema']; |
|
785 | 4 | $foreignTableName = $constraint[0]['ref_table']; |
|
786 | 4 | $onDelete = $constraint[0]['on_delete']; |
|
787 | 4 | $onUpdate = $constraint[0]['on_update']; |
|
788 | |||
789 | static $onRuleMap = [ |
||
790 | 'C' => 'CASCADE', |
||
791 | 'N' => 'SET NULL', |
||
792 | 'R' => 'RESTRICT', |
||
793 | 4 | ]; |
|
794 | |||
795 | 4 | $result[] = new \yii\db\ForeignKeyConstraint([ |
|
796 | 4 | 'name' => $name, |
|
797 | 4 | 'columnNames' => $columns, |
|
798 | 4 | 'foreignSchemaName' => $foreignSchemaName, |
|
799 | 4 | 'foreignTableName' => $foreignTableName, |
|
800 | 4 | 'foreignColumnNames' => $foreignColumnNames, |
|
801 | 4 | 'onUpdate' => isset($onRuleMap[$onUpdate]) ? $onRuleMap[$onUpdate] : null, |
|
802 | 4 | 'onDelete' => isset($onRuleMap[$onDelete]) ? $onRuleMap[$onDelete] : null, |
|
803 | 4 | ]); |
|
804 | 4 | } |
|
805 | 4 | return $result; |
|
806 | } |
||
807 | |||
808 | 27 | protected function loadTableIndexes($tableName) { |
|
809 | 27 | $resolvedName = $this->resolveTableName($tableName); |
|
810 | |||
811 | $sql = <<<SQL |
||
812 | SELECT i.indname AS name, |
||
813 | ic.colname AS column_name, |
||
814 | CASE i.uniquerule |
||
815 | WHEN 'U' THEN 1 |
||
816 | WHEN 'P' THEN 1 |
||
817 | ELSE 0 |
||
818 | END AS index_is_unique, |
||
819 | CASE i.uniquerule |
||
820 | WHEN 'P' THEN 1 |
||
821 | ELSE 0 |
||
822 | END AS index_is_primary |
||
823 | FROM syscat.indexes AS i |
||
824 | INNER JOIN syscat.indexcoluse AS ic |
||
825 | ON ic.indschema = i.indschema |
||
826 | AND ic.indname = i.indname |
||
827 | WHERE i.ownertype != 'S' |
||
828 | AND i.tabname = :table |
||
829 | 27 | SQL; |
|
830 | |||
831 | 27 | if ($resolvedName->sequenceName) { |
|
832 | $sql .= ' AND i.tabschema = :schema'; |
||
833 | } |
||
834 | |||
835 | 27 | $sql .= ' ORDER BY ic.colseq'; |
|
836 | |||
837 | 27 | $command = $this->db->createCommand($sql); |
|
838 | |||
839 | 27 | $command->bindValue(':table', $resolvedName->name); |
|
840 | |||
841 | 27 | if ($resolvedName->sequenceName) { |
|
842 | $command->bindValue(':schema', $resolvedName->sequenceName); |
||
843 | } |
||
844 | |||
845 | 27 | $constraints = $command->queryAll(); |
|
846 | 27 | $constraints = $this->normalizePdoRowKeyCase($constraints, true); |
|
847 | 27 | $constraints = \yii\helpers\ArrayHelper::index($constraints, null, ['name']); |
|
848 | 27 | $result = []; |
|
849 | 27 | foreach ($constraints as $name => $constraint) { |
|
850 | 24 | $columns = \yii\helpers\ArrayHelper::getColumn($constraint, 'column_name'); |
|
851 | |||
852 | 24 | $isUnique = $constraint[0]['index_is_unique']; |
|
853 | 24 | $isPrimary = $constraint[0]['index_is_primary']; |
|
854 | |||
855 | 24 | $result[] = new \yii\db\IndexConstraint([ |
|
856 | 24 | 'name' => $name, |
|
857 | 24 | 'columnNames' => $columns, |
|
858 | 24 | 'isUnique' => !!$isUnique, |
|
859 | 24 | 'isPrimary' => !!$isPrimary, |
|
860 | 24 | ]); |
|
861 | 27 | } |
|
862 | 27 | return $result; |
|
863 | } |
||
864 | |||
865 | 252 | protected function normalizePdoRowKeyCase(array $row, $multiple) |
|
866 | { |
||
867 | 252 | if ($this->db->getSlavePdo()->getAttribute(\PDO::ATTR_CASE) === \PDO::CASE_LOWER) { |
|
868 | 20 | return $row; |
|
869 | } |
||
870 | |||
871 | 232 | if ($multiple) { |
|
872 | 232 | return array_map(function (array $row) { |
|
873 | 220 | return array_change_key_case($row, CASE_LOWER); |
|
874 | 232 | }, $row); |
|
875 | } |
||
876 | |||
877 | return array_change_key_case($row, CASE_LOWER); |
||
878 | } |
||
879 | } |
||
880 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..