Skip to content

Commit b96f09b

Browse files
committed
Query builder Like tests.
1 parent 9521545 commit b96f09b

File tree

2 files changed

+146
-12
lines changed

2 files changed

+146
-12
lines changed

system/Database/BaseBuilder.php

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -766,9 +766,8 @@ protected function whereHaving($qb_key, $key, $value = null, $type = 'AND ', $es
766766
{
767767
$op = $this->getOperator($k);
768768
$k = trim(str_replace($op, '', $k));
769-
$ok = $k;
770769

771-
$this->binds[$k] = $v;
770+
$bind = $this->setBind($k, $v);
772771

773772
if (empty($op))
774773
{
@@ -789,7 +788,7 @@ protected function whereHaving($qb_key, $key, $value = null, $type = 'AND ', $es
789788
$k = substr($k, 0, $match[0][1]).($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL');
790789
}
791790

792-
$v = ! is_null($v) ? ' :'.$ok : $v;
791+
$v = ! is_null($v) ? ' :'.$bind : $v;
793792

794793
$this->{$qb_key}[] = ['condition' => $prefix.$k.$v, 'escape' => $escape];
795794
if ($this->QBCaching === true)
@@ -1047,7 +1046,8 @@ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $n
10471046
$field = [$field => $match];
10481047
}
10491048

1050-
is_bool($escape) OR $escape = $this->protectIdentifiers;
1049+
$escape = is_bool($escape) ? $escape : $this->protectIdentifiers;
1050+
10511051
// lowercase $side in case somebody writes e.g. 'BEFORE' instead of 'before' (doh)
10521052
$side = strtolower($side);
10531053

@@ -1056,26 +1056,23 @@ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $n
10561056
$prefix = (count($this->QBWhere) === 0 && count($this->QBCacheWhere) === 0)
10571057
? $this->groupGetType('') : $this->groupGetType($type);
10581058

1059-
if ($escape === true)
1060-
{
1061-
$v = $this->escape_like_str($v);
1062-
}
1059+
$bind = $this->setBind($k, $v);
10631060

10641061
if ($side === 'none')
10651062
{
1066-
$like_statement = "{$prefix} {$k} {$not} LIKE '{$v}'";
1063+
$like_statement = "{$prefix} {$k} {$not} LIKE ':{$bind}'";
10671064
}
10681065
elseif ($side === 'before')
10691066
{
1070-
$like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}'";
1067+
$like_statement = "{$prefix} {$k} {$not} LIKE '%:{$bind}'";
10711068
}
10721069
elseif ($side === 'after')
10731070
{
1074-
$like_statement = "{$prefix} {$k} {$not} LIKE '{$v}%'";
1071+
$like_statement = "{$prefix} {$k} {$not} LIKE ':{$bind}%'";
10751072
}
10761073
else
10771074
{
1078-
$like_statement = "{$prefix} {$k} {$not} LIKE '%{$v}%'";
1075+
$like_statement = "{$prefix} {$k} {$not} LIKE '%:{$bind}%'";
10791076
}
10801077

10811078
// some platforms require an escape sequence definition for LIKE wildcards
@@ -3313,4 +3310,33 @@ protected function getOperator($str)
33133310
}
33143311

33153312
// --------------------------------------------------------------------
3313+
3314+
/**
3315+
* Stores a bind value after ensuring that it's unique.
3316+
*
3317+
* @param string $key
3318+
* @param null $value
3319+
*/
3320+
protected function setBind(string $key, $value = null)
3321+
{
3322+
if (! array_key_exists($key, $this->binds))
3323+
{
3324+
$this->binds[$key] = $value;
3325+
return $key;
3326+
}
3327+
3328+
$count = 0;
3329+
3330+
while (array_key_exists($key.$count, $this->binds))
3331+
{
3332+
++$count;
3333+
}
3334+
3335+
$this->binds[$key.$count] = $value;
3336+
3337+
return $key.$count;
3338+
}
3339+
3340+
//--------------------------------------------------------------------
3341+
33163342
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php namespace Builder;
2+
3+
use CodeIgniter\Database\BaseBuilder;
4+
use CodeIgniter\Database\MockConnection;
5+
6+
class LikeTest extends \CIUnitTestCase
7+
{
8+
protected $db;
9+
10+
//--------------------------------------------------------------------
11+
12+
public function setUp()
13+
{
14+
$this->db = new MockConnection([]);
15+
}
16+
17+
//--------------------------------------------------------------------
18+
19+
public function testSimpleLike()
20+
{
21+
$builder = new BaseBuilder('job', $this->db);
22+
23+
$builder->like('name', 'veloper');
24+
25+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%:name%' ESCAPE '!'";
26+
$expectedBinds = ['name' => 'veloper'];
27+
28+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
29+
$this->assertSame($expectedBinds, $builder->getBinds());
30+
}
31+
32+
//--------------------------------------------------------------------
33+
34+
public function testLikeBeforeOnly()
35+
{
36+
$builder = new BaseBuilder('job', $this->db);
37+
38+
$builder->like('name', 'veloper', 'before');
39+
40+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%:name' ESCAPE '!'";
41+
$expectedBinds = ['name' => 'veloper'];
42+
43+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
44+
$this->assertSame($expectedBinds, $builder->getBinds());
45+
}
46+
47+
//--------------------------------------------------------------------
48+
49+
public function testLikeAfterOnly()
50+
{
51+
$builder = new BaseBuilder('job', $this->db);
52+
53+
$builder->like('name', 'veloper', 'after');
54+
55+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE ':name%' ESCAPE '!'";
56+
$expectedBinds = ['name' => 'veloper'];
57+
58+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
59+
$this->assertSame($expectedBinds, $builder->getBinds());
60+
}
61+
62+
//--------------------------------------------------------------------
63+
64+
public function testOrLike()
65+
{
66+
$builder = new BaseBuilder('job', $this->db);
67+
68+
$builder->like('name', 'veloper')->orLike('name', 'ian');
69+
70+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%:name%' ESCAPE '!' OR \"name\" LIKE '%:name0%' ESCAPE '!'";
71+
$expectedBinds = ['name' => 'veloper', 'name0' => 'ian'];
72+
73+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
74+
$this->assertSame($expectedBinds, $builder->getBinds());
75+
}
76+
77+
//--------------------------------------------------------------------
78+
79+
public function testNotLike()
80+
{
81+
$builder = new BaseBuilder('job', $this->db);
82+
83+
$builder->notLike('name', 'veloper');
84+
85+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" NOT LIKE '%:name%' ESCAPE '!'";
86+
$expectedBinds = ['name' => 'veloper'];
87+
88+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
89+
$this->assertSame($expectedBinds, $builder->getBinds());
90+
}
91+
92+
//--------------------------------------------------------------------
93+
94+
public function testOrNotLike()
95+
{
96+
$builder = new BaseBuilder('job', $this->db);
97+
98+
$builder->like('name', 'veloper')->orNotLike('name', 'ian');
99+
100+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%:name%' ESCAPE '!' OR \"name\" NOT LIKE '%:name0%' ESCAPE '!'";
101+
$expectedBinds = ['name' => 'veloper', 'name0' => 'ian'];
102+
103+
$this->assertEquals($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
104+
$this->assertSame($expectedBinds, $builder->getBinds());
105+
}
106+
107+
//--------------------------------------------------------------------
108+
}

0 commit comments

Comments
 (0)