Skip to content

Commit 4ba835d

Browse files
authored
refactor(database): optimize groupGetType by caching it inside BaseBuilder loops (#10340)
1 parent ad03579 commit 4ba835d

3 files changed

Lines changed: 128 additions & 5 deletions

File tree

system/Database/BaseBuilder.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,14 +764,18 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type
764764
$keyValue = $key;
765765
}
766766

767+
if ($keyValue === []) {
768+
return $this;
769+
}
770+
767771
// If the escape value was not set will base it on the global setting
768772
if (! is_bool($escape)) {
769773
$escape = $this->db->protectIdentifiers;
770774
}
771775

772-
foreach ($keyValue as $k => $v) {
773-
$prefix = empty($this->{$qbKey}) ? $this->groupGetType('') : $this->groupGetType($type);
776+
$prefix = empty($this->{$qbKey}) ? $this->groupGetType('') : $this->groupGetType($type);
774777

778+
foreach ($keyValue as $k => $v) {
775779
if ($rawSqlOnly) {
776780
$k = '';
777781
$op = '';
@@ -830,6 +834,8 @@ protected function whereHaving(string $qbKey, $key, $value = null, string $type
830834
'escape' => $escape,
831835
];
832836
}
837+
838+
$prefix = $type;
833839
}
834840

835841
return $this;
@@ -1152,13 +1158,17 @@ protected function _like($field, string $match = '', string $type = 'AND ', stri
11521158

11531159
$keyValue = is_array($field) ? $field : [$field => $match];
11541160

1161+
if ($keyValue === []) {
1162+
return $this;
1163+
}
1164+
1165+
$prefix = $this->{$clause} === [] ? $this->groupGetType('') : $this->groupGetType($type);
1166+
11551167
foreach ($keyValue as $k => $v) {
11561168
if ($insensitiveSearch) {
11571169
$v = mb_strtolower($v, 'UTF-8');
11581170
}
11591171

1160-
$prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type);
1161-
11621172
if ($side === 'none') {
11631173
$bind = $this->setBind($k, $v, $escape);
11641174
} elseif ($side === 'before') {
@@ -1180,6 +1190,8 @@ protected function _like($field, string $match = '', string $type = 'AND ', stri
11801190
'condition' => $likeStatement,
11811191
'escape' => $escape,
11821192
];
1193+
1194+
$prefix = $type;
11831195
}
11841196

11851197
return $this;

tests/system/Database/Builder/LikeTest.php

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use CodeIgniter\Database\RawSql;
1818
use CodeIgniter\Test\CIUnitTestCase;
1919
use CodeIgniter\Test\Mock\MockConnection;
20+
use PHPUnit\Framework\Attributes\DataProvider;
2021
use PHPUnit\Framework\Attributes\Group;
2122

2223
/**
@@ -231,4 +232,114 @@ public function testDBPrefixAndCoulmnWithTablename(): void
231232
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
232233
$this->assertSame($expectedBinds, $builder->getBinds());
233234
}
235+
236+
public function testLikeMultipleFields(): void
237+
{
238+
$builder = new BaseBuilder('job', $this->db);
239+
240+
$builder->like([
241+
'name' => 'veloper',
242+
'title' => 'dev',
243+
]);
244+
245+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%veloper%' ESCAPE '!' AND \"title\" LIKE '%dev%' ESCAPE '!'";
246+
$expectedBinds = [
247+
'name' => [
248+
'%veloper%',
249+
true,
250+
],
251+
'title' => [
252+
'%dev%',
253+
true,
254+
],
255+
];
256+
257+
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
258+
$this->assertSame($expectedBinds, $builder->getBinds());
259+
}
260+
261+
public function testLikeMultipleCallsWithRawSqlAndString(): void
262+
{
263+
$builder = new BaseBuilder('users', $this->db);
264+
265+
$sql = "concat(users.name, ' ', users.surname)";
266+
$rawSql = new RawSql($sql);
267+
268+
$builder->like($rawSql, 'value')->like('name', 'veloper');
269+
270+
$expectedSQL = "SELECT * FROM \"users\" WHERE {$sql} LIKE '%value%' ESCAPE '!' AND \"name\" LIKE '%veloper%' ESCAPE '!'";
271+
$expectedBinds = [
272+
$rawSql->getBindingKey() => [
273+
'%value%',
274+
true,
275+
],
276+
'name' => [
277+
'%veloper%',
278+
true,
279+
],
280+
];
281+
282+
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
283+
$this->assertSame($expectedBinds, $builder->getBinds());
284+
}
285+
286+
public function testOrLikeMultipleFields(): void
287+
{
288+
$builder = new BaseBuilder('job', $this->db);
289+
290+
$builder->orLike([
291+
'name' => 'veloper',
292+
'title' => 'dev',
293+
]);
294+
295+
$expectedSQL = "SELECT * FROM \"job\" WHERE \"name\" LIKE '%veloper%' ESCAPE '!' OR \"title\" LIKE '%dev%' ESCAPE '!'";
296+
$expectedBinds = [
297+
'name' => [
298+
'%veloper%',
299+
true,
300+
],
301+
'title' => [
302+
'%dev%',
303+
true,
304+
],
305+
];
306+
307+
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
308+
$this->assertSame($expectedBinds, $builder->getBinds());
309+
}
310+
311+
#[DataProvider('provideLikeMethodsWithEmptyArray')]
312+
public function testLikeMethodsWithEmptyArray(string $method): void
313+
{
314+
$builder = new BaseBuilder('job', $this->db);
315+
316+
$builder->groupStart()
317+
->{$method}([])
318+
->where('id', 1)
319+
->groupEnd();
320+
321+
$expectedSQL = 'SELECT * FROM "job" WHERE ( "id" = 1 )';
322+
$expectedBinds = [
323+
'id' => [
324+
1,
325+
true,
326+
],
327+
];
328+
329+
$this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledSelect()));
330+
$this->assertSame($expectedBinds, $builder->getBinds());
331+
}
332+
333+
/**
334+
* @return array<string, array{0: string}>
335+
*/
336+
public static function provideLikeMethodsWithEmptyArray(): iterable
337+
{
338+
return [
339+
'like' => ['like'],
340+
'orLike' => ['orLike'],
341+
'notLike' => ['notLike'],
342+
'orNotLike' => ['orNotLike'],
343+
];
344+
}
234345
}

utils/phpstan-baseline/empty.notAllowed.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ parameters:
3434

3535
-
3636
message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#'
37-
count: 28
37+
count: 27
3838
path: ../../system/Database/BaseBuilder.php
3939

4040
-

0 commit comments

Comments
 (0)