Skip to content

Commit 6000d30

Browse files
committed
feat: join() supports RawSql
1 parent c3fd096 commit 6000d30

4 files changed

Lines changed: 45 additions & 8 deletions

File tree

system/Database/BaseBuilder.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,11 @@ public function fromSubquery(BaseBuilder $from, string $alias): self
579579
/**
580580
* Generates the JOIN portion of the query
581581
*
582+
* @param RawSql|string $cond
583+
*
582584
* @return $this
583585
*/
584-
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
586+
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
585587
{
586588
if ($type !== '') {
587589
$type = strtoupper(trim($type));
@@ -601,6 +603,17 @@ public function join(string $table, string $cond, string $type = '', ?bool $esca
601603
$escape = $this->db->protectIdentifiers;
602604
}
603605

606+
// Do we want to escape the table name?
607+
if ($escape === true) {
608+
$table = $this->db->protectIdentifiers($table, true, null, false);
609+
}
610+
611+
if ($cond instanceof RawSql) {
612+
$this->QBJoin[] = $type . 'JOIN ' . $table . ' ON ' . $cond;
613+
614+
return $this;
615+
}
616+
604617
if (! $this->hasOperator($cond)) {
605618
$cond = ' USING (' . ($escape ? $this->db->escapeIdentifiers($cond) : $cond) . ')';
606619
} elseif ($escape === false) {
@@ -634,11 +647,6 @@ public function join(string $table, string $cond, string $type = '', ?bool $esca
634647
}
635648
}
636649

637-
// Do we want to escape the table name?
638-
if ($escape === true) {
639-
$table = $this->db->protectIdentifiers($table, true, null, false);
640-
}
641-
642650
// Assemble the JOIN statement
643651
$this->QBJoin[] = $type . 'JOIN ' . $table . $cond;
644652

system/Database/Postgre/Builder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use CodeIgniter\Database\BaseBuilder;
1515
use CodeIgniter\Database\Exceptions\DatabaseException;
16+
use CodeIgniter\Database\RawSql;
1617

1718
/**
1819
* Builder for Postgre
@@ -300,9 +301,11 @@ protected function _like_statement(?string $prefix, string $column, ?string $not
300301
/**
301302
* Generates the JOIN portion of the query
302303
*
304+
* @param RawSql|string $cond
305+
*
303306
* @return BaseBuilder
304307
*/
305-
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
308+
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
306309
{
307310
if (! in_array('FULL OUTER', $this->joinTypes, true)) {
308311
$this->joinTypes = array_merge($this->joinTypes, ['FULL OUTER']);

system/Database/SQLSRV/Builder.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use CodeIgniter\Database\BaseBuilder;
1515
use CodeIgniter\Database\Exceptions\DatabaseException;
1616
use CodeIgniter\Database\Exceptions\DataException;
17+
use CodeIgniter\Database\RawSql;
1718
use CodeIgniter\Database\ResultInterface;
1819

1920
/**
@@ -88,9 +89,11 @@ protected function _truncate(string $table): string
8889
/**
8990
* Generates the JOIN portion of the query
9091
*
92+
* @param RawSql|string $cond
93+
*
9194
* @return $this
9295
*/
93-
public function join(string $table, string $cond, string $type = '', ?bool $escape = null)
96+
public function join(string $table, $cond, string $type = '', ?bool $escape = null)
9497
{
9598
if ($type !== '') {
9699
$type = strtoupper(trim($type));

tests/system/Database/Builder/JoinTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use CodeIgniter\Database\BaseBuilder;
1515
use CodeIgniter\Database\Postgre\Builder as PostgreBuilder;
16+
use CodeIgniter\Database\RawSql;
1617
use CodeIgniter\Database\SQLSRV\Builder as SQLSRVBuilder;
1718
use CodeIgniter\Test\CIUnitTestCase;
1819
use CodeIgniter\Test\Mock\MockConnection;
@@ -75,6 +76,28 @@ public function testJoinMultipleConditions()
7576
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
7677
}
7778

79+
/**
80+
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3832
81+
*/
82+
public function testJoinRawSql()
83+
{
84+
$builder = new BaseBuilder('device', $this->db);
85+
86+
$sql = 'user.id = device.user_id
87+
AND (
88+
(1=1 OR 1=1)
89+
OR
90+
(1=1 OR 1=1)
91+
)';
92+
$builder->join('user', new RawSql($sql), 'LEFT');
93+
94+
$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) )';
95+
96+
$output = str_replace("\n", ' ', $builder->getCompiledSelect());
97+
$output = preg_replace('/\s+/', ' ', $output);
98+
$this->assertSame($expectedSQL, $output);
99+
}
100+
78101
public function testFullOuterJoin()
79102
{
80103
$builder = new PostgreBuilder('jobs', $this->db);

0 commit comments

Comments
 (0)