From b0ed2d511c79a9289a689880e9929d546678f68e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 11 Jul 2022 14:00:24 +0900 Subject: [PATCH 1/4] fix: invalid INSERT query when builder uses table alias --- system/Database/BaseBuilder.php | 17 ++++++++++-- tests/system/Database/Builder/InsertTest.php | 29 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 4f835730d176..a5903c49625b 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -1863,7 +1863,7 @@ public function getCompiledInsert(bool $reset = true) } $sql = $this->_insert( - $this->db->protectIdentifiers($this->QBFrom[0], true, null, false), + $this->db->protectIdentifiers($this->removeAlias($this->QBFrom[0]), true, null, false), array_keys($this->QBSet), array_values($this->QBSet) ); @@ -1895,7 +1895,7 @@ public function insert($set = null, ?bool $escape = null) } $sql = $this->_insert( - $this->db->protectIdentifiers($this->QBFrom[0], true, $escape, false), + $this->db->protectIdentifiers($this->removeAlias($this->QBFrom[0]), true, $escape, false), array_keys($this->QBSet), array_values($this->QBSet) ); @@ -1914,6 +1914,19 @@ public function insert($set = null, ?bool $escape = null) return false; } + protected function removeAlias(string $from): string + { + if (strpos($from, ' ') !== false) { + // if the alias is written with the AS keyword, remove it + $from = preg_replace('/\s+AS\s+/i', ' ', $from); + + $parts = explode(' ', $from); + $from = $parts[0]; + } + + return $from; + } + /** * This method is used by both insert() and getCompiledInsert() to * validate that the there data is actually being set and that table diff --git a/tests/system/Database/Builder/InsertTest.php b/tests/system/Database/Builder/InsertTest.php index daa605be40f9..774dd1082ed0 100644 --- a/tests/system/Database/Builder/InsertTest.php +++ b/tests/system/Database/Builder/InsertTest.php @@ -85,6 +85,35 @@ public function testInsertObject() $this->assertSame($expectedBinds, $builder->getBinds()); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/5365 + */ + public function testInsertWithTableAlias() + { + $builder = $this->db->table('jobs as j'); + + $insertData = [ + 'id' => 1, + 'name' => 'Grocery Sales', + ]; + $builder->testMode()->insert($insertData, true); + + $expectedSQL = 'INSERT INTO "jobs" ("id", "name") VALUES (1, \'Grocery Sales\')'; + $expectedBinds = [ + 'id' => [ + 1, + true, + ], + 'name' => [ + 'Grocery Sales', + true, + ], + ]; + + $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledInsert())); + $this->assertSame($expectedBinds, $builder->getBinds()); + } + public function testThrowsExceptionOnNoValuesSet() { $builder = $this->db->table('jobs'); From dd279db1103223bc1bd63efff013b7c29613fd0d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 17:36:43 +0900 Subject: [PATCH 2/4] style: break long lines --- system/Database/BaseBuilder.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index a5903c49625b..958292b1a820 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -1863,7 +1863,12 @@ public function getCompiledInsert(bool $reset = true) } $sql = $this->_insert( - $this->db->protectIdentifiers($this->removeAlias($this->QBFrom[0]), true, null, false), + $this->db->protectIdentifiers( + $this->removeAlias($this->QBFrom[0]), + true, + null, + false + ), array_keys($this->QBSet), array_values($this->QBSet) ); @@ -1895,7 +1900,12 @@ public function insert($set = null, ?bool $escape = null) } $sql = $this->_insert( - $this->db->protectIdentifiers($this->removeAlias($this->QBFrom[0]), true, $escape, false), + $this->db->protectIdentifiers( + $this->removeAlias($this->QBFrom[0]), + true, + $escape, + false + ), array_keys($this->QBSet), array_values($this->QBSet) ); From bd5ac2475816493abaa954ee106bfc0ffeeaba5e Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 23 Nov 2021 20:26:31 +0900 Subject: [PATCH 3/4] fix: invalid DELETE query when builder uses table alias --- system/Database/BaseBuilder.php | 2 +- tests/system/Database/Builder/DeleteTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 958292b1a820..e4b399f5fbee 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -2363,7 +2363,7 @@ public function delete($where = '', ?int $limit = null, bool $resetData = true) return false; // @codeCoverageIgnore } - $sql = $this->_delete($table); + $sql = $this->_delete($this->removeAlias($table)); if (! empty($limit)) { $this->QBLimit = $limit; diff --git a/tests/system/Database/Builder/DeleteTest.php b/tests/system/Database/Builder/DeleteTest.php index 777a646992c4..ab27a2ec9266 100644 --- a/tests/system/Database/Builder/DeleteTest.php +++ b/tests/system/Database/Builder/DeleteTest.php @@ -60,6 +60,20 @@ public function testGetCompiledDelete() $this->assertSame($expectedSQL, $sql); } + public function testGetCompiledDeleteWithTableAlias() + { + $builder = $this->db->table('jobs j'); + + $builder->where('id', 1); + $sql = $builder->getCompiledDelete(); + + $expectedSQL = <<<'EOL' + DELETE FROM "jobs" + WHERE "id" = 1 + EOL; + $this->assertSame($expectedSQL, $sql); + } + public function testGetCompiledDeleteWithLimit() { $builder = $this->db->table('jobs'); From a8b0edd5a1d8d36daeb874100314b10342a81b5a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 12 Jul 2022 17:43:18 +0900 Subject: [PATCH 4/4] docs: add @internal --- system/Database/BaseBuilder.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index e4b399f5fbee..a899ffbe5628 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -1924,6 +1924,12 @@ public function insert($set = null, ?bool $escape = null) return false; } + /** + * @internal This is a temporary solution. + * + * @see https://github.com/codeigniter4/CodeIgniter4/pull/5376 + * @TODO Fix a root cause, and this method should be removed. + */ protected function removeAlias(string $from): string { if (strpos($from, ' ') !== false) {