diff --git a/system/BaseModel.php b/system/BaseModel.php index bc484e1cd646..792a1f3580eb 100644 --- a/system/BaseModel.php +++ b/system/BaseModel.php @@ -1050,6 +1050,10 @@ public function replace(array $data = null, bool $returnSQL = false) return false; } + if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, (array) $data)) { + $data[$this->updatedField] = $this->setDate(); + } + return $this->doReplace($data, $returnSQL); } diff --git a/system/Database/Postgre/Builder.php b/system/Database/Postgre/Builder.php index dab246add915..a0c865dbfc05 100644 --- a/system/Database/Postgre/Builder.php +++ b/system/Database/Postgre/Builder.php @@ -137,18 +137,16 @@ public function decrement(string $column, int $value = 1) //-------------------------------------------------------------------- /** - * Replace - * - * Compiles an replace into string and runs the query. + * Compiles a replace into string and runs the query. * Because PostgreSQL doesn't support the replace into command, * we simply do a DELETE and an INSERT on the first key/value * combo, assuming that it's either the primary key or a unique key. * * @param array $set An associative array of insert values * - * @return mixed - * @throws DatabaseException - * @internal param true $bool returns the generated SQL, false executes the query. + * @return mixed + * + * @throws DatabaseException */ public function replace(array $set = null) { @@ -160,24 +158,32 @@ public function replace(array $set = null) if (CI_DEBUG) { throw new DatabaseException('You must use the "set" method to update an entry.'); } - // @codeCoverageIgnoreStart - return false; - // @codeCoverageIgnoreEnd + + return false; // @codeCoverageIgnore } $table = $this->QBFrom[0]; + $set = $this->binds; + + array_walk($set, static function (array &$item) { + $item = $item[0]; + }); $key = array_key_first($set); $value = $set[$key]; $builder = $this->db->table($table); - $exists = $builder->where("$key = $value", null, false)->get()->getFirstRow(); + $exists = $builder->where($key, $value, true)->get()->getFirstRow(); - if (empty($exists)) { + if (empty($exists) && $this->testMode) { + $result = $this->getCompiledInsert(); + } elseif (empty($exists)) { $result = $builder->insert($set); + } elseif ($this->testMode) { + $result = $this->where($key, $value, true)->getCompiledUpdate(); } else { - array_pop($set); - $result = $builder->update($set, "$key = $value"); + array_shift($set); + $result = $builder->where($key, $value, true)->update($set); } unset($builder); diff --git a/system/Database/SQLSRV/Builder.php b/system/Database/SQLSRV/Builder.php index d5df00488c3a..fbf01f5fc6ec 100755 --- a/system/Database/SQLSRV/Builder.php +++ b/system/Database/SQLSRV/Builder.php @@ -415,9 +415,9 @@ protected function _replace(string $table, array $keys, array $values): string $bingo = []; foreach ($common as $v) { - $k = array_search($v, $escKeyFields, true); + $k = array_search($v, $keys, true); - $bingo[$keyFields[$k]] = $binds[trim($values[$k], ':')]; + $bingo[$keys[$k]] = $binds[trim($values[$k], ':')]; } // Querying existing data diff --git a/tests/system/Models/ReplaceModelTest.php b/tests/system/Models/ReplaceModelTest.php new file mode 100644 index 000000000000..2820d21d0517 --- /dev/null +++ b/tests/system/Models/ReplaceModelTest.php @@ -0,0 +1,32 @@ +createModel(UserModel::class); + + $data = [ + 'name' => 'Amanda Holmes', + 'email' => 'amanda@holmes.com', + 'country' => 'US', + ]; + + $id = $this->model->insert($data); + + $data['id'] = $id; + $data['country'] = 'UK'; + + $sql = $this->model->replace($data, true); + $this->assertStringNotContainsString('updated_at', $sql); + + $this->model = $this->createModel(UserModel::class); + $this->setPrivateProperty($this->model, 'useTimestamps', true); + $sql = $this->model->replace($data, true); + $this->assertStringContainsString('updated_at', $sql); + } +}