Skip to content

Commit 95c33ca

Browse files
authored
prefer json_value(...) over json_unquote(json_extract(...)) (#57417)
1 parent 446a1a5 commit 95c33ca

File tree

4 files changed

+93
-5
lines changed

4 files changed

+93
-5
lines changed

src/Illuminate/Database/Query/Grammars/MariaDbGrammar.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,17 @@ public function useLegacyGroupLimit(Builder $query)
5353
{
5454
return false;
5555
}
56+
57+
/**
58+
* Wrap the given JSON selector.
59+
*
60+
* @param string $value
61+
* @return string
62+
*/
63+
protected function wrapJsonSelector($value)
64+
{
65+
[$field, $path] = $this->wrapJsonFieldAndPath($value);
66+
67+
return 'json_value('.$field.$path.')';
68+
}
5669
}

src/Illuminate/Database/Schema/Grammars/MariaDbGrammar.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,17 @@ protected function typeGeometry(Fluent $column)
5151
$column->srid ? ' ref_system_id='.$column->srid : ''
5252
);
5353
}
54+
55+
/**
56+
* Wrap the given JSON selector.
57+
*
58+
* @param string $value
59+
* @return string
60+
*/
61+
protected function wrapJsonSelector($value)
62+
{
63+
[$field, $path] = $this->wrapJsonFieldAndPath($value);
64+
65+
return 'json_value('.$field.$path.')';
66+
}
5467
}

tests/Database/DatabaseMariaDbSchemaGrammarTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,7 @@ public function testCreateTableWithVirtualAsColumn()
14351435
$statements = $blueprint->toSql();
14361436

14371437
$this->assertCount(1, $statements);
1438-
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_unquote(json_extract(`my_json_column`, '$.\"some_attribute\"'))))", $statements[0]);
1438+
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_value(`my_json_column`, '$.\"some_attribute\"')))", $statements[0]);
14391439

14401440
$conn = $this->getConnection();
14411441
$conn->shouldReceive('getConfig')->andReturn(null);
@@ -1448,7 +1448,7 @@ public function testCreateTableWithVirtualAsColumn()
14481448
$statements = $blueprint->toSql();
14491449

14501450
$this->assertCount(1, $statements);
1451-
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_unquote(json_extract(`my_json_column`, '$.\"some_attribute\".\"nested\"'))))", $statements[0]);
1451+
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_value(`my_json_column`, '$.\"some_attribute\".\"nested\"')))", $statements[0]);
14521452
}
14531453

14541454
public function testCreateTableWithVirtualAsColumnWhenJsonColumnHasArrayKey()
@@ -1463,7 +1463,7 @@ public function testCreateTableWithVirtualAsColumnWhenJsonColumnHasArrayKey()
14631463
$statements = $blueprint->toSql();
14641464

14651465
$this->assertCount(1, $statements);
1466-
$this->assertSame("create table `users` (`my_json_column` varchar(255) as (json_unquote(json_extract(`my_json_column`, '$.\"foo\"[0][1]'))))", $statements[0]);
1466+
$this->assertSame("create table `users` (`my_json_column` varchar(255) as (json_value(`my_json_column`, '$.\"foo\"[0][1]')))", $statements[0]);
14671467
}
14681468

14691469
public function testCreateTableWithStoredAsColumn()
@@ -1494,7 +1494,7 @@ public function testCreateTableWithStoredAsColumn()
14941494
$statements = $blueprint->toSql();
14951495

14961496
$this->assertCount(1, $statements);
1497-
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_unquote(json_extract(`my_json_column`, '$.\"some_attribute\"'))) stored)", $statements[0]);
1497+
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_value(`my_json_column`, '$.\"some_attribute\"')) stored)", $statements[0]);
14981498

14991499
$conn = $this->getConnection();
15001500
$conn->shouldReceive('getConfig')->andReturn(null);
@@ -1507,7 +1507,7 @@ public function testCreateTableWithStoredAsColumn()
15071507
$statements = $blueprint->toSql();
15081508

15091509
$this->assertCount(1, $statements);
1510-
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_unquote(json_extract(`my_json_column`, '$.\"some_attribute\".\"nested\"'))) stored)", $statements[0]);
1510+
$this->assertSame("create table `users` (`my_json_column` varchar(255) not null, `my_other_column` varchar(255) as (json_value(`my_json_column`, '$.\"some_attribute\".\"nested\"')) stored)", $statements[0]);
15111511
}
15121512

15131513
public function testDropDatabaseIfExists()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Database\MariaDb;
4+
5+
use Illuminate\Database\Schema\Blueprint;
6+
use Illuminate\Support\Facades\DB;
7+
use Illuminate\Support\Facades\Schema;
8+
use PHPUnit\Framework\Attributes\RequiresOperatingSystem;
9+
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
10+
11+
#[RequiresOperatingSystem('Linux|Darwin')]
12+
#[RequiresPhpExtension('pdo_mysql')]
13+
class JsonLikeTest extends MariaDbTestCase
14+
{
15+
protected function afterRefreshingDatabase()
16+
{
17+
Schema::create('tasks', function (Blueprint $table) {
18+
$table->id();
19+
$table->json('data');
20+
});
21+
}
22+
23+
protected function destroyDatabaseMigrations()
24+
{
25+
Schema::dropIfExists('tasks');
26+
}
27+
28+
public function testJsonLikeWithEmoji()
29+
{
30+
// Test that LIKE queries work correctly with emojis in JSON fields
31+
// This verifies that json_value() handles emojis correctly (unlike json_unquote)
32+
DB::table('tasks')->insert([
33+
['data' => '{"status":"Building started 🔨"}'],
34+
['data' => '{"status":"Tests passed ✅"}'],
35+
['data' => '{"status":"Deployment complete 🌎"}'],
36+
]);
37+
38+
// Search for records containing the hammer emoji
39+
$buildCount = DB::table('tasks')
40+
->where('data->status', 'like', '%🔨%')
41+
->count();
42+
$this->assertSame(1, $buildCount, 'Should find 1 record with hammer emoji');
43+
44+
// Search for records containing "Tests" with emoji
45+
$testsCount = DB::table('tasks')
46+
->where('data->status', 'like', '%Tests%')
47+
->count();
48+
$this->assertSame(1, $testsCount, 'Should find 1 record with "Tests"');
49+
50+
// Search for records containing rocket emoji
51+
$deployCount = DB::table('tasks')
52+
->where('data->status', 'like', '%🌎%')
53+
->count();
54+
$this->assertSame(1, $deployCount, 'Should find 1 record with globe emoji');
55+
56+
// Verify we can find text before emoji
57+
$completeCount = DB::table('tasks')
58+
->where('data->status', 'like', '%complete%')
59+
->count();
60+
$this->assertSame(1, $completeCount, 'Should find 1 record with "complete" before emoji');
61+
}
62+
}

0 commit comments

Comments
 (0)