Skip to content

Commit

Permalink
Unquote JSON values on MySQL (#25732)
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir authored and taylorotwell committed Sep 21, 2018
1 parent b4c0c24 commit 24c8197
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 38 deletions.
7 changes: 3 additions & 4 deletions src/Illuminate/Database/Query/Grammars/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -966,16 +966,15 @@ protected function wrapJsonSelector($value)
* Split the given JSON selector into the field and the optional path and wrap them separately.
*
* @param string $column
* @param string $delimiter
* @return array
*/
protected function wrapJsonFieldAndPath($column, $delimiter = '->')
protected function wrapJsonFieldAndPath($column)
{
$parts = explode($delimiter, $column, 2);
$parts = explode('->', $column, 2);

$field = $this->wrap($parts[0]);

$path = count($parts) > 1 ? ', '.$this->wrapJsonPath($parts[1], $delimiter) : '';
$path = count($parts) > 1 ? ', '.$this->wrapJsonPath($parts[1], '->') : '';

return [$field, $path];
}
Expand Down
13 changes: 2 additions & 11 deletions src/Illuminate/Database/Query/Grammars/MySqlGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Illuminate\Database\Query\Grammars;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JsonExpression;

Expand Down Expand Up @@ -319,16 +318,8 @@ protected function wrapValue($value)
*/
protected function wrapJsonSelector($value)
{
$delimiter = Str::contains($value, '->>') ? '->>' : '->';
list($field, $path) = $this->wrapJsonFieldAndPath($value);

list($field, $path) = $this->wrapJsonFieldAndPath($value, $delimiter);

$selector = 'json_extract('.$field.$path.')';

if ($delimiter === '->>') {
$selector = 'json_unquote('.$selector.')';
}

return $selector;
return 'json_unquote(json_extract('.$field.$path.'))';
}
}
31 changes: 8 additions & 23 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2031,7 +2031,7 @@ public function testMySqlWrappingJsonWithString()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->sku', '=', 'foo-bar');
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."sku"\') = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."sku"\')) = ?', $builder->toSql());
$this->assertCount(1, $builder->getRawBindings()['where']);
$this->assertEquals('foo-bar', $builder->getRawBindings()['where'][0]);
}
Expand All @@ -2040,43 +2040,28 @@ public function testMySqlWrappingJsonWithInteger()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->price', '=', 1);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."price"\') = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."price"\')) = ?', $builder->toSql());
}

public function testMySqlWrappingJsonWithDouble()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->price', '=', 1.5);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."price"\') = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."price"\')) = ?', $builder->toSql());
}

public function testMySqlWrappingJsonWithBoolean()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->available', '=', true);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."available"\') = true', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."available"\')) = true', $builder->toSql());
}

public function testMySqlWrappingJsonWithBooleanAndIntegerThatLooksLikeOne()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->available', '=', true)->where('items->active', '=', false)->where('items->number_available', '=', 0);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."available"\') = true and json_extract(`items`, \'$."active"\') = false and json_extract(`items`, \'$."number_available"\') = ?', $builder->toSql());
}

public function testMySqlWrappingJsonWithoutQuote()
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->>sku', '=', 'foo-bar');
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."sku"\')) = ?', $builder->toSql());
$this->assertCount(1, $builder->getRawBindings()['where']);
$this->assertEquals('foo-bar', $builder->getRawBindings()['where'][0]);

$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->>price->>in_usd', '=', 'foo-bar');
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."price"."in_usd"\')) = ?', $builder->toSql());
$this->assertCount(1, $builder->getRawBindings()['where']);
$this->assertEquals('foo-bar', $builder->getRawBindings()['where'][0]);
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."available"\')) = true and json_unquote(json_extract(`items`, \'$."active"\')) = false and json_unquote(json_extract(`items`, \'$."number_available"\')) = ?', $builder->toSql());
}

public function testMySqlWrappingJson()
Expand All @@ -2087,15 +2072,15 @@ public function testMySqlWrappingJson()

$builder = $this->getMySqlBuilder();
$builder->select('items->price')->from('users')->where('users.items->price', '=', 1)->orderBy('items->price');
$this->assertEquals('select json_extract(`items`, \'$."price"\') from `users` where json_extract(`users`.`items`, \'$."price"\') = ? order by json_extract(`items`, \'$."price"\') asc', $builder->toSql());
$this->assertEquals('select json_unquote(json_extract(`items`, \'$."price"\')) from `users` where json_unquote(json_extract(`users`.`items`, \'$."price"\')) = ? order by json_unquote(json_extract(`items`, \'$."price"\')) asc', $builder->toSql());

$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->price->in_usd', '=', 1);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."price"."in_usd"\') = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."price"."in_usd"\')) = ?', $builder->toSql());

$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->price->in_usd', '=', 1)->where('items->age', '=', 2);
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."price"."in_usd"\') = ? and json_extract(`items`, \'$."age"\') = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."price"."in_usd"\')) = ? and json_unquote(json_extract(`items`, \'$."age"\')) = ?', $builder->toSql());
}

public function testPostgresWrappingJson()
Expand Down

0 comments on commit 24c8197

Please sign in to comment.