|
28 | 28 | class Schema extends \yii\db\Schema |
29 | 29 | { |
30 | 30 |
|
31 | | - private $_sequences = []; |
32 | 31 | private $_lastInsertID = null; |
33 | 32 |
|
34 | 33 | /** |
@@ -95,16 +94,6 @@ protected function loadTableSchema($name) |
95 | 94 | $this->resolveTableNames($table, $name); |
96 | 95 | if ($this->findColumns($table)) { |
97 | 96 | $this->findConstraints($table); |
98 | | - if (is_string($table->primaryKey) && isset($this->_sequences[$table->fullName . '.' . $table->primaryKey])) { |
99 | | - $table->sequenceName = $this->_sequences[$table->fullName . '.' . $table->primaryKey]; |
100 | | - } elseif (is_array($table->primaryKey)) { |
101 | | - foreach ($table->primaryKey as $pk) { |
102 | | - if (isset($this->_sequences[$table->fullName . '.' . $pk])) { |
103 | | - $table->sequenceName = $this->_sequences[$table->fullName . '.' . $pk]; |
104 | | - break; |
105 | | - } |
106 | | - } |
107 | | - } |
108 | 97 | return $table; |
109 | 98 | } |
110 | 99 | return null; |
@@ -164,7 +153,7 @@ protected function findColumns($table) |
164 | 153 | fld.rdb$field_precision AS fprecision, |
165 | 154 | rel.rdb$null_flag AS fnull, |
166 | 155 | fld.rdb$default_value AS fdefault_value, |
167 | | - (SELECT 1 FROM RDB$TRIGGERS |
| 156 | + (SELECT RDB$TRIGGER_SOURCE FROM RDB$TRIGGERS |
168 | 157 | WHERE RDB$SYSTEM_FLAG = 0 |
169 | 158 | AND UPPER(RDB$RELATION_NAME)=UPPER(\'' . $table->name . '\') |
170 | 159 | AND RDB$TRIGGER_TYPE = 1 |
@@ -207,8 +196,13 @@ protected function findColumns($table) |
207 | 196 | } |
208 | 197 | foreach ($columns as $column) { |
209 | 198 | $c = $this->loadColumnSchema($column); |
210 | | - if ($c->autoIncrement) { |
211 | | - $this->_sequences[$table->fullName . '.' . $c->name] = $table->fullName . '.' . $c->name; |
| 199 | + if ($table->sequenceName === null && $c->autoIncrement) { |
| 200 | + $matches = []; |
| 201 | + if (preg_match("/NEW.{$c->name}\s*=\s*GEN_ID\((\w+)/i", $column['fautoinc'], $matches)) { |
| 202 | + $table->sequenceName = $matches[1]; |
| 203 | + } elseif (preg_match("/NEW.{$c->name}\s*=\s*NEXT\s+VALUE\s+FOR\s+(\w+)/i", $column['fautoinc'], $matches)) { |
| 204 | + $table->sequenceName = $matches[1]; |
| 205 | + } |
212 | 206 | } |
213 | 207 | $table->columns[$c->name] = $c; |
214 | 208 | if ($c->isPrimaryKey) { |
@@ -239,7 +233,7 @@ protected function loadColumnSchema($column) |
239 | 233 | $c->name = strtolower(rtrim($column['fname'])); |
240 | 234 | $c->allowNull = $column['fnull'] !== '1'; |
241 | 235 | $c->isPrimaryKey = $column['fprimary']; |
242 | | - $c->autoIncrement = $column['fautoinc'] === '1'; |
| 236 | + $c->autoIncrement = (boolean)$column['fautoinc']; |
243 | 237 |
|
244 | 238 | $c->type = self::TYPE_STRING; |
245 | 239 |
|
@@ -345,7 +339,7 @@ protected function loadColumnSchema($column) |
345 | 339 |
|
346 | 340 | $c->defaultValue = null; |
347 | 341 | if ($defaultValue !== null) { |
348 | | - if (in_array($c->type, [self::TYPE_DATE, self::TYPE_DATETIME, self::TYPE_TIME, self::TYPE_TIMESTAMP]) |
| 342 | + if (in_array($c->type, [self::TYPE_DATE, self::TYPE_DATETIME, self::TYPE_TIME, self::TYPE_TIMESTAMP]) |
349 | 343 | && preg_match('/(CURRENT_|NOW|NULL|TODAY|TOMORROW|YESTERDAY)/i', $defaultValue)) { |
350 | 344 | $c->defaultValue = new \yii\db\Expression(trim($defaultValue)); |
351 | 345 | } else { |
@@ -443,53 +437,53 @@ public function setTransactionIsolationLevel($level) |
443 | 437 | } |
444 | 438 |
|
445 | 439 | /** |
446 | | - * Executes the INSERT command, returning primary key values. |
447 | | - * @param string $table the table that new rows will be inserted into. |
448 | | - * @param array $columns the column data (name => value) to be inserted into the table. |
449 | | - * @return array primary key values or false if the command fails |
450 | | - * @since 2.0.4 |
| 440 | + * @inheritdoc |
451 | 441 | */ |
452 | 442 | public function insert($table, $columns) |
453 | 443 | { |
| 444 | + $this->_lastInsertID = false; |
| 445 | + $params = []; |
| 446 | + $sql = $this->db->getQueryBuilder()->insert($table, $columns, $params); |
| 447 | + $returnColumns = $this->getTableSchema($table)->primaryKey; |
| 448 | + if (!empty($returnColumns)) { |
| 449 | + $returning = []; |
| 450 | + foreach ((array)$returnColumns as $name) { |
| 451 | + $returning[] = $this->quoteColumnName($name); |
| 452 | + } |
| 453 | + $sql .= ' RETURNING ' . implode(', ', $returning); |
| 454 | + } |
454 | 455 |
|
455 | | - $tableSchema = $this->getTableSchema($table); |
456 | | - |
457 | | - $command = $this->db->createCommand()->insert($table, $columns); |
| 456 | + $command = $this->db->createCommand($sql, $params); |
| 457 | + $command->prepare(false); |
| 458 | + $result = $command->queryOne(); |
458 | 459 |
|
459 | | - if ($tableSchema->sequenceName !== null) { |
460 | | - $this->_lastInsertID = $command->queryScalar(); |
461 | | - if ($this->_lastInsertID === false) { |
462 | | - return false; |
463 | | - } |
| 460 | + if (!$command->pdoStatement->rowCount()) { |
| 461 | + return false; |
464 | 462 | } else { |
465 | | - if (!$command->execute()) { |
466 | | - return false; |
467 | | - } |
468 | | - } |
469 | | - $result = []; |
470 | | - foreach ($tableSchema->primaryKey as $name) { |
471 | | - if ($tableSchema->columns[$name]->autoIncrement) { |
472 | | - $result[$name] = $this->getLastInsertID($tableSchema->sequenceName); |
473 | | - break; |
474 | | - } else { |
475 | | - $result[$name] = isset($columns[$name]) ? $columns[$name] : $tableSchema->columns[$name]->defaultValue; |
| 463 | + if (!empty($returnColumns)) { |
| 464 | + foreach ((array)$returnColumns as $name) { |
| 465 | + if ($this->getTableSchema($table)->getColumn($name)->autoIncrement) { |
| 466 | + $this->_lastInsertID = $result[$name]; |
| 467 | + break; |
| 468 | + } |
| 469 | + } |
476 | 470 | } |
| 471 | + return $result; |
477 | 472 | } |
478 | | - return $result; |
479 | 473 | } |
480 | 474 |
|
481 | 475 | /** |
482 | | - * Returns the ID of the last inserted row or sequence value. |
483 | | - * @param string $sequenceName name of the sequence object (required by some DBMS) |
484 | | - * @return string the row ID of the last row inserted, or the last value retrieved from the sequence object |
485 | | - * @throws InvalidCallException if the DB connection is not active |
486 | | - * @see http://www.php.net/manual/en/function.PDO-lastInsertId.php |
| 476 | + * @inheritdoc |
487 | 477 | */ |
488 | 478 | public function getLastInsertID($sequenceName = '') |
489 | 479 | { |
490 | 480 | if (!$this->db->isActive) { |
491 | 481 | throw new InvalidCallException('DB Connection is not active.'); |
492 | 482 | } |
| 483 | + |
| 484 | + if ($sequenceName !== '') { |
| 485 | + return $this->db->createCommand('SELECT GEN_ID('. $this->db->quoteTableName($sequenceName) . ', 0 ) FROM RDB$DATABASE;')->queryScalar(); |
| 486 | + } |
493 | 487 |
|
494 | 488 | if ($this->_lastInsertID !== false) { |
495 | 489 | return $this->_lastInsertID; |
|
0 commit comments