Skip to content

Commit

Permalink
feat: join() supports RawSql
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Apr 7, 2022
1 parent acdfbec commit 8d1ac3e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
20 changes: 14 additions & 6 deletions system/Database/BaseBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -579,9 +579,11 @@ public function fromSubquery(BaseBuilder $from, string $alias): self
/**
* Generates the JOIN portion of the query
*
* @param RawSql|string $cond
*
* @return $this
*/
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
{
if ($type !== '') {
$type = strtoupper(trim($type));
Expand All @@ -601,6 +603,17 @@ public function join(string $table, string $cond, string $type = '', ?bool $esca
$escape = $this->db->protectIdentifiers;
}

// Do we want to escape the table name?
if ($escape === true) {
$table = $this->db->protectIdentifiers($table, true, null, false);
}

if ($cond instanceof RawSql) {
$this->QBJoin[] = $type . 'JOIN ' . $table . ' ON ' . $cond;

return $this;
}

if (! $this->hasOperator($cond)) {
$cond = ' USING (' . ($escape ? $this->db->escapeIdentifiers($cond) : $cond) . ')';
} elseif ($escape === false) {
Expand Down Expand Up @@ -634,11 +647,6 @@ public function join(string $table, string $cond, string $type = '', ?bool $esca
}
}

// Do we want to escape the table name?
if ($escape === true) {
$table = $this->db->protectIdentifiers($table, true, null, false);
}

// Assemble the JOIN statement
$this->QBJoin[] = $type . 'JOIN ' . $table . $cond;

Expand Down
5 changes: 4 additions & 1 deletion system/Database/Postgre/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Database\RawSql;

/**
* Builder for Postgre
Expand Down Expand Up @@ -300,9 +301,11 @@ protected function _like_statement(?string $prefix, string $column, ?string $not
/**
* Generates the JOIN portion of the query
*
* @param RawSql|string $cond
*
* @return BaseBuilder
*/
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
{
if (! in_array('FULL OUTER', $this->joinTypes, true)) {
$this->joinTypes = array_merge($this->joinTypes, ['FULL OUTER']);
Expand Down
5 changes: 4 additions & 1 deletion system/Database/SQLSRV/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Database\Exceptions\DataException;
use CodeIgniter\Database\RawSql;
use CodeIgniter\Database\ResultInterface;

/**
Expand Down Expand Up @@ -88,9 +89,11 @@ protected function _truncate(string $table): string
/**
* Generates the JOIN portion of the query
*
* @param RawSql|string $cond
*
* @return $this
*/
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
{
if ($type !== '') {
$type = strtoupper(trim($type));
Expand Down
23 changes: 23 additions & 0 deletions tests/system/Database/Builder/JoinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\Postgre\Builder as PostgreBuilder;
use CodeIgniter\Database\RawSql;
use CodeIgniter\Database\SQLSRV\Builder as SQLSRVBuilder;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Mock\MockConnection;
Expand Down Expand Up @@ -75,6 +76,28 @@ public function testJoinMultipleConditions()
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
}

/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3832
*/
public function testJoinRawSql()
{
$builder = new BaseBuilder('device', $this->db);

$sql = 'user.id = device.user_id
AND (
(1=1 OR 1=1)
OR
(1=1 OR 1=1)
)';
$builder->join('user', new RawSql($sql), 'LEFT');

$expectedSQL = 'SELECT * FROM "device" LEFT JOIN "user" ON user.id = device.user_id AND ( (1=1 OR 1=1) OR (1=1 OR 1=1) )';

$output = str_replace("\n", ' ', $builder->getCompiledSelect());
$output = preg_replace('/\s+/', ' ', $output);
$this->assertSame($expectedSQL, $output);
}

public function testFullOuterJoin()
{
$builder = new PostgreBuilder('jobs', $this->db);
Expand Down

0 comments on commit 8d1ac3e

Please sign in to comment.