Skip to content

Commit

Permalink
Merge pull request #5376 from kenjis/fix-5365-builder-insert
Browse files Browse the repository at this point in the history
fix: invalid INSERT/DELETE query when Query Builder uses table alias
  • Loading branch information
kenjis committed Jul 14, 2022
2 parents 537e896 + a8b0edd commit 72963d0
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
35 changes: 32 additions & 3 deletions system/Database/BaseBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1863,7 +1863,12 @@ 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)
);
Expand Down Expand Up @@ -1895,7 +1900,12 @@ 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)
);
Expand All @@ -1914,6 +1924,25 @@ 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) {
// 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
Expand Down Expand Up @@ -2340,7 +2369,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;
Expand Down
14 changes: 14 additions & 0 deletions tests/system/Database/Builder/DeleteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
29 changes: 29 additions & 0 deletions tests/system/Database/Builder/InsertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down

0 comments on commit 72963d0

Please sign in to comment.