Skip to content

Commit fc19b69

Browse files
michalsndatamweb
andauthored
fix: case-insensitivity in the like() method when in use with accented characters (codeigniter4#9238)
* fix: case-insensitivity in the like() method when in use with accented characters * Update system/Database/BaseBuilder.php Co-authored-by: Pooya Parsa <[email protected]> * add more cases for tests * even more tests * fix types * set collation for sqlsrv --------- Co-authored-by: Pooya Parsa <[email protected]>
1 parent 3d0f9f2 commit fc19b69

File tree

9 files changed

+62
-10
lines changed

9 files changed

+62
-10
lines changed

.github/workflows/reusable-phpunit-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ jobs:
138138
steps:
139139
- name: Create database for MSSQL Server
140140
if: ${{ inputs.db-platform == 'SQLSRV' }}
141-
run: sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q "CREATE DATABASE test"
141+
run: sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q "CREATE DATABASE test COLLATE Latin1_General_100_CS_AS_SC_UTF8"
142142

143143
- name: Install latest ImageMagick
144144
if: ${{ contains(inputs.extra-extensions, 'imagick') }}

system/Database/BaseBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ protected function _like($field, string $match = '', string $type = 'AND ', stri
11511151

11521152
foreach ($keyValue as $k => $v) {
11531153
if ($insensitiveSearch) {
1154-
$v = strtolower($v);
1154+
$v = mb_strtolower($v, 'UTF-8');
11551155
}
11561156

11571157
$prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type);

system/Database/SQLSRV/Forge.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,10 @@ protected function _alterTable(string $alterType, string $table, $processedField
212212

213213
$sql = <<<SQL
214214
SELECT name
215-
FROM SYS.DEFAULT_CONSTRAINTS
216-
WHERE PARENT_OBJECT_ID = OBJECT_ID('{$fullTable}')
217-
AND PARENT_COLUMN_ID IN (
218-
SELECT column_id FROM sys.columns WHERE NAME IN ({$fields}) AND object_id = OBJECT_ID(N'{$fullTable}')
215+
FROM sys.default_constraints
216+
WHERE parent_object_id = OBJECT_ID('{$fullTable}')
217+
AND parent_column_id IN (
218+
SELECT column_id FROM sys.columns WHERE name IN ({$fields}) AND object_id = OBJECT_ID(N'{$fullTable}')
219219
)
220220
SQL;
221221

tests/_support/Database/Migrations/20160428212500_Create_test_tables.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public function up(): void
9292

9393
if ($this->db->DBDriver === 'SQLSRV') {
9494
unset($dataTypeFields['type_timestamp']);
95+
$dataTypeFields['type_text'] = ['type' => 'NVARCHAR(max)', 'null' => true];
9596
}
9697

9798
if ($this->db->DBDriver === 'Postgre' || $this->db->DBDriver === 'SQLSRV') {

tests/_support/Database/Seeds/CITestSeeder.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,26 @@ public function run(): void
8686
'key' => 'key',
8787
'value' => 'value',
8888
],
89+
[
90+
'key' => 'multibyte characters pl',
91+
'value' => 'śćźżłąęó',
92+
],
93+
[
94+
'key' => 'multibyte characters fa',
95+
'value' => 'خٌوب',
96+
],
97+
[
98+
'key' => 'multibyte characters bn',
99+
'value' => 'টাইপ',
100+
],
101+
[
102+
'key' => 'multibyte characters ko',
103+
'value' => '캐스팅',
104+
],
105+
[
106+
'key' => 'multibyte characters ml',
107+
'value' => 'ടൈപ്പ്',
108+
],
89109
],
90110
'type_test' => [
91111
[

tests/system/Database/Live/ForgeTest.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,9 +1615,15 @@ public function testDropKey(): void
16151615
public function testAddTextColumnWithConstraint(): void
16161616
{
16171617
// some DBMS do not allow a constraint for type TEXT
1618-
$this->forge->addColumn('user', [
1619-
'text_with_constraint' => ['type' => 'text', 'constraint' => 255, 'default' => ''],
1620-
]);
1618+
if ($this->db->DBDriver === 'SQLSRV') {
1619+
$this->forge->addColumn('user', [
1620+
'text_with_constraint' => ['type' => 'nvarchar(max)', 'default' => ''],
1621+
]);
1622+
} else {
1623+
$this->forge->addColumn('user', [
1624+
'text_with_constraint' => ['type' => 'text', 'constraint' => 255, 'default' => ''],
1625+
]);
1626+
}
16211627

16221628
$this->assertTrue($this->db->fieldExists('text_with_constraint', 'user'));
16231629

tests/system/Database/Live/GetTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public function testGetFieldData(): void
178178
$this->assertSame('int', $typeTest[0]->type_name); // INTEGER AUTOINC
179179
$this->assertSame('varchar', $typeTest[1]->type_name); // VARCHAR
180180
$this->assertSame('char', $typeTest[2]->type_name); // CHAR
181-
$this->assertSame('text', $typeTest[3]->type_name); // TEXT
181+
$this->assertSame('nvarchar', $typeTest[3]->type_name); // TEXT
182182
$this->assertSame('smallint', $typeTest[4]->type_name); // SMALLINT
183183
$this->assertSame('int', $typeTest[5]->type_name); // INTEGER
184184
$this->assertSame('float', $typeTest[6]->type_name); // FLOAT

tests/system/Database/Live/LikeTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use CodeIgniter\Database\RawSql;
1717
use CodeIgniter\Test\CIUnitTestCase;
1818
use CodeIgniter\Test\DatabaseTestTrait;
19+
use PHPUnit\Framework\Attributes\DataProvider;
1920
use PHPUnit\Framework\Attributes\Group;
2021
use Tests\Support\Database\Seeds\CITestSeeder;
2122

@@ -75,6 +76,29 @@ public function testLikeCaseInsensitive(): void
7576
$this->assertSame('Developer', $job->name);
7677
}
7778

79+
#[DataProvider('provideMultibyteCharacters')]
80+
public function testLikeCaseInsensitiveWithMultibyteCharacter(string $match, string $result): void
81+
{
82+
$wai = $this->db->table('without_auto_increment')->like('value', $match, 'both', null, true)->get();
83+
$wai = $wai->getRow();
84+
85+
$this->assertSame($result, $wai->key);
86+
}
87+
88+
/**
89+
* @return iterable<string, array{0: string, 1: string}>
90+
*/
91+
public static function provideMultibyteCharacters(): iterable
92+
{
93+
yield from [
94+
'polish' => ['ŁĄ', 'multibyte characters pl'],
95+
'farsi' => ['خٌوب', 'multibyte characters fa'],
96+
'bengali' => ['টাইপ', 'multibyte characters bn'],
97+
'korean' => ['캐스팅', 'multibyte characters ko'],
98+
'malayalam' => ['ടൈപ്പ്', 'multibyte characters ml'],
99+
];
100+
}
101+
78102
public function testOrLike(): void
79103
{
80104
$jobs = $this->db->table('job')->like('name', 'ian')

user_guide_src/source/changelogs/v4.5.6.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Bugs Fixed
3232
- **Session Library:** The session initialization debug message now uses the correct log type "debug" instead of "info".
3333

3434
- **Validation:** Fixed the `getValidated()` method that did not return valid data when validation rules used multiple asterisks.
35+
- **Database:** Fixed the case insensitivity option in the ``like()`` method when dealing with accented characters.
3536

3637
- **Parser:** Fixed bug that caused equal key names to be replaced by the key name defined first.
3738

0 commit comments

Comments
 (0)