Merge pull request #8792 from kenjis/fix-QB-join-BETWEEN

fix: [QueryBuilder] TypeError in join() with BETWEEN
This commit is contained in:
kenjis 2024-04-30 09:31:06 +09:00 committed by GitHub
commit 31343505e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 0 deletions

View File

@ -654,6 +654,7 @@ class BaseBuilder
$cond = ' ON ' . $cond;
} else {
// Split multiple conditions
// @TODO This does not parse `BETWEEN a AND b` correctly.
if (preg_match_all('/\sAND\s|\sOR\s/i', $cond, $joints, PREG_OFFSET_CAPTURE)) {
$conditions = [];
$joints = $joints[0];
@ -676,6 +677,13 @@ class BaseBuilder
foreach ($conditions as $i => $condition) {
$operator = $this->getOperator($condition);
// Workaround for BETWEEN
if ($operator === false) {
$cond .= $joints[$i] . $condition;
continue;
}
$cond .= $joints[$i];
$cond .= preg_match('/(\(*)?([\[\]\w\.\'-]+)' . preg_quote($operator, '/') . '(.*)/i', $condition, $match) ? $match[1] . $this->db->protectIdentifiers($match[2]) . $operator . $this->db->protectIdentifiers($match[3]) : $condition;
}

View File

@ -145,6 +145,13 @@ class Builder extends BaseBuilder
foreach ($conditions as $i => $condition) {
$operator = $this->getOperator($condition);
// Workaround for BETWEEN
if ($operator === false) {
$cond .= $joints[$i] . $condition;
continue;
}
$cond .= $joints[$i];
$cond .= preg_match('/(\(*)?([\[\]\w\.\'-]+)' . preg_quote($operator, '/') . '(.*)/i', $condition, $match) ? $match[1] . $this->db->protectIdentifiers($match[2]) . $operator . $this->db->protectIdentifiers($match[3]) : $condition;
}

View File

@ -80,6 +80,25 @@ final class JoinTest extends CIUnitTestCase
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
}
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/8791
*/
public function testJoinMultipleConditionsBetween(): void
{
$builder = new BaseBuilder('table1', $this->db);
$builder->join(
'leases',
'units.unit_id = leases.unit_id AND CURDATE() BETWEEN lease_start_date AND lease_exp_date',
'LEFT'
);
// @TODO Should be `... CURDATE() BETWEEN "lease_start_date" AND "lease_exp_date"`
$expectedSQL = 'SELECT * FROM "table1" LEFT JOIN "leases" ON "units"."unit_id" = "leases"."unit_id" AND CURDATE() BETWEEN lease_start_date AND lease_exp_date';
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
}
/**
* @see https://github.com/codeigniter4/CodeIgniter4/issues/3832
*/