Skip to content

Commit 04c68b4

Browse files
committed
feat: where() supports RawSql
1 parent e8687c7 commit 04c68b4

2 files changed

Lines changed: 50 additions & 20 deletions

File tree

system/Database/BaseBuilder.php

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public function ignore(bool $ignore = true)
356356
/**
357357
* Generates the SELECT portion of the query
358358
*
359-
* @param array|string $select
359+
* @param array|RawSql|string $select
360360
*
361361
* @return $this
362362
*/
@@ -649,8 +649,8 @@ public function join(string $table, string $cond, string $type = '', ?bool $esca
649649
* Generates the WHERE portion of the query.
650650
* Separates multiple calls with 'AND'.
651651
*
652-
* @param mixed $key
653-
* @param mixed $value
652+
* @param array|RawSql|string $key
653+
* @param mixed $value
654654
*
655655
* @return $this
656656
*/
@@ -665,9 +665,9 @@ public function where($key, $value = null, ?bool $escape = null)
665665
* Generates the WHERE portion of the query.
666666
* Separates multiple calls with 'OR'.
667667
*
668-
* @param mixed $key
669-
* @param mixed $value
670-
* @param bool $escape
668+
* @param array|RawSql|string $key
669+
* @param mixed $value
670+
* @param bool $escape
671671
*
672672
* @return $this
673673
*/
@@ -682,26 +682,34 @@ public function orWhere($key, $value = null, ?bool $escape = null)
682682
* @used-by having()
683683
* @used-by orHaving()
684684
*
685-
* @param mixed $key
686-
* @param mixed $value
685+
* @param array|RawSql|string $key
686+
* @param mixed $value
687687
*
688688
* @return $this
689689
*/
690690
protected function whereHaving(string $qbKey, $key, $value = null, string $type = 'AND ', ?bool $escape = null)
691691
{
692-
if (! is_array($key)) {
693-
$key = [$key => $value];
692+
if ($key instanceof RawSql) {
693+
$keyValue = [(string) $key => $key];
694+
$escape = false;
695+
} elseif (! is_array($key)) {
696+
$keyValue = [$key => $value];
697+
} else {
698+
$keyValue = $key;
694699
}
695700

696701
// If the escape value was not set will base it on the global setting
697702
if (! is_bool($escape)) {
698703
$escape = $this->db->protectIdentifiers;
699704
}
700705

701-
foreach ($key as $k => $v) {
706+
foreach ($keyValue as $k => $v) {
702707
$prefix = empty($this->{$qbKey}) ? $this->groupGetType('') : $this->groupGetType($type);
703708

704-
if ($v !== null) {
709+
if ($v instanceof RawSql) {
710+
$k = '';
711+
$op = '';
712+
} elseif ($v !== null) {
705713
$op = $this->getOperator($k, true);
706714

707715
if (! empty($op)) {
@@ -737,10 +745,17 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type
737745
$op = '';
738746
}
739747

740-
$this->{$qbKey}[] = [
741-
'condition' => $prefix . $k . $op . $v,
742-
'escape' => $escape,
743-
];
748+
if ($v instanceof RawSql) {
749+
$this->{$qbKey}[] = [
750+
'condition' => $v->with($prefix . $k . $op . $v),
751+
'escape' => $escape,
752+
];
753+
} else {
754+
$this->{$qbKey}[] = [
755+
'condition' => $prefix . $k . $op . $v,
756+
'escape' => $escape,
757+
];
758+
}
744759
}
745760

746761
return $this;
@@ -1275,8 +1290,8 @@ public function groupBy($by, ?bool $escape = null)
12751290
/**
12761291
* Separates multiple calls with 'AND'.
12771292
*
1278-
* @param array|string $key
1279-
* @param mixed $value
1293+
* @param array|RawSql|string $key
1294+
* @param mixed $value
12801295
*
12811296
* @return $this
12821297
*/
@@ -1288,8 +1303,8 @@ public function having($key, $value = null, ?bool $escape = null)
12881303
/**
12891304
* Separates multiple calls with 'OR'.
12901305
*
1291-
* @param array|string $key
1292-
* @param mixed $value
1306+
* @param array|RawSql|string $key
1307+
* @param mixed $value
12931308
*
12941309
* @return $this
12951310
*/

tests/system/Database/Builder/WhereTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace CodeIgniter\Database\Builder;
1313

1414
use CodeIgniter\Database\BaseBuilder;
15+
use CodeIgniter\Database\RawSql;
1516
use CodeIgniter\Test\CIUnitTestCase;
1617
use CodeIgniter\Test\Mock\MockConnection;
1718
use stdClass;
@@ -140,6 +141,20 @@ public function testWhereCustomString()
140141
$this->assertSame($expectedBinds, $builder->getBinds());
141142
}
142143

144+
public function testWhereRawSql()
145+
{
146+
$builder = $this->db->table('jobs');
147+
148+
$sql = "id > 2 AND name != 'Accountant'";
149+
$builder->where(new RawSql($sql));
150+
151+
$expectedSQL = "SELECT * FROM \"jobs\" WHERE id > 2 AND name != 'Accountant'";
152+
$expectedBinds = [];
153+
154+
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
155+
$this->assertSame($expectedBinds, $builder->getBinds());
156+
}
157+
143158
public function testWhereValueSubQuery()
144159
{
145160
$expectedSQL = 'SELECT * FROM "neworder" WHERE "advance_amount" < (SELECT MAX(advance_amount) FROM "orders" WHERE "id" > 2)';

0 commit comments

Comments
 (0)