Skip to content

Commit

Permalink
fix: case-insensitivity in the like() method when in use with accen…
Browse files Browse the repository at this point in the history
…ted characters (#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]>
  • Loading branch information
michalsn and datamweb authored Nov 3, 2024
1 parent 3d0f9f2 commit fc19b69
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/reusable-phpunit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ jobs:
steps:
- name: Create database for MSSQL Server
if: ${{ inputs.db-platform == 'SQLSRV' }}
run: sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q "CREATE DATABASE test"
run: sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q "CREATE DATABASE test COLLATE Latin1_General_100_CS_AS_SC_UTF8"

- name: Install latest ImageMagick
if: ${{ contains(inputs.extra-extensions, 'imagick') }}
Expand Down
2 changes: 1 addition & 1 deletion system/Database/BaseBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ protected function _like($field, string $match = '', string $type = 'AND ', stri

foreach ($keyValue as $k => $v) {
if ($insensitiveSearch) {
$v = strtolower($v);
$v = mb_strtolower($v, 'UTF-8');
}

$prefix = empty($this->{$clause}) ? $this->groupGetType('') : $this->groupGetType($type);
Expand Down
8 changes: 4 additions & 4 deletions system/Database/SQLSRV/Forge.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ protected function _alterTable(string $alterType, string $table, $processedField

$sql = <<<SQL
SELECT name
FROM SYS.DEFAULT_CONSTRAINTS
WHERE PARENT_OBJECT_ID = OBJECT_ID('{$fullTable}')
AND PARENT_COLUMN_ID IN (
SELECT column_id FROM sys.columns WHERE NAME IN ({$fields}) AND object_id = OBJECT_ID(N'{$fullTable}')
FROM sys.default_constraints
WHERE parent_object_id = OBJECT_ID('{$fullTable}')
AND parent_column_id IN (
SELECT column_id FROM sys.columns WHERE name IN ({$fields}) AND object_id = OBJECT_ID(N'{$fullTable}')
)
SQL;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public function up(): void

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

if ($this->db->DBDriver === 'Postgre' || $this->db->DBDriver === 'SQLSRV') {
Expand Down
20 changes: 20 additions & 0 deletions tests/_support/Database/Seeds/CITestSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,26 @@ public function run(): void
'key' => 'key',
'value' => 'value',
],
[
'key' => 'multibyte characters pl',
'value' => 'śćźżłąęó',
],
[
'key' => 'multibyte characters fa',
'value' => 'خٌوب',
],
[
'key' => 'multibyte characters bn',
'value' => 'টাইপ',
],
[
'key' => 'multibyte characters ko',
'value' => '캐스팅',
],
[
'key' => 'multibyte characters ml',
'value' => 'ടൈപ്പ്',
],
],
'type_test' => [
[
Expand Down
12 changes: 9 additions & 3 deletions tests/system/Database/Live/ForgeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1615,9 +1615,15 @@ public function testDropKey(): void
public function testAddTextColumnWithConstraint(): void
{
// some DBMS do not allow a constraint for type TEXT
$this->forge->addColumn('user', [
'text_with_constraint' => ['type' => 'text', 'constraint' => 255, 'default' => ''],
]);
if ($this->db->DBDriver === 'SQLSRV') {
$this->forge->addColumn('user', [
'text_with_constraint' => ['type' => 'nvarchar(max)', 'default' => ''],
]);
} else {
$this->forge->addColumn('user', [
'text_with_constraint' => ['type' => 'text', 'constraint' => 255, 'default' => ''],
]);
}

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

Expand Down
2 changes: 1 addition & 1 deletion tests/system/Database/Live/GetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public function testGetFieldData(): void
$this->assertSame('int', $typeTest[0]->type_name); // INTEGER AUTOINC
$this->assertSame('varchar', $typeTest[1]->type_name); // VARCHAR
$this->assertSame('char', $typeTest[2]->type_name); // CHAR
$this->assertSame('text', $typeTest[3]->type_name); // TEXT
$this->assertSame('nvarchar', $typeTest[3]->type_name); // TEXT
$this->assertSame('smallint', $typeTest[4]->type_name); // SMALLINT
$this->assertSame('int', $typeTest[5]->type_name); // INTEGER
$this->assertSame('float', $typeTest[6]->type_name); // FLOAT
Expand Down
24 changes: 24 additions & 0 deletions tests/system/Database/Live/LikeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use CodeIgniter\Database\RawSql;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use Tests\Support\Database\Seeds\CITestSeeder;

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

#[DataProvider('provideMultibyteCharacters')]
public function testLikeCaseInsensitiveWithMultibyteCharacter(string $match, string $result): void
{
$wai = $this->db->table('without_auto_increment')->like('value', $match, 'both', null, true)->get();
$wai = $wai->getRow();

$this->assertSame($result, $wai->key);
}

/**
* @return iterable<string, array{0: string, 1: string}>
*/
public static function provideMultibyteCharacters(): iterable
{
yield from [
'polish' => ['ŁĄ', 'multibyte characters pl'],
'farsi' => ['خٌوب', 'multibyte characters fa'],
'bengali' => ['টাইপ', 'multibyte characters bn'],
'korean' => ['캐스팅', 'multibyte characters ko'],
'malayalam' => ['ടൈപ്പ്', 'multibyte characters ml'],
];
}

public function testOrLike(): void
{
$jobs = $this->db->table('job')->like('name', 'ian')
Expand Down
1 change: 1 addition & 0 deletions user_guide_src/source/changelogs/v4.5.6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Bugs Fixed
- **Session Library:** The session initialization debug message now uses the correct log type "debug" instead of "info".

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

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

Expand Down

0 comments on commit fc19b69

Please sign in to comment.