Skip to content

Commit

Permalink
Add JSON SELECT queries to SQL Server
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed May 31, 2018
1 parent 6d000a8 commit a8def08
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
31 changes: 30 additions & 1 deletion src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\Database\Query\Grammars;

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

class SqlServerGrammar extends Grammar
Expand Down Expand Up @@ -411,7 +412,35 @@ public function getDateFormat()
*/
protected function wrapValue($value)
{
return $value === '*' ? $value : '['.str_replace(']', ']]', $value).']';
if ($value === '*') {
return $value;
}

// If the given value is a JSON selector we will wrap it differently than a
// traditional value. We will need to split this path and wrap each part
// wrapped, etc. Otherwise, we will simply wrap the value as a string.
if (Str::contains($value, '->')) {
return $this->wrapJsonSelector($value);
}

return '['.str_replace(']', ']]', $value).']';
}

/**
* Wrap the given JSON selector.
*
* @param string $value
* @return string
*/
protected function wrapJsonSelector($value)
{
$path = explode('->', $value);

$field = $this->wrapValue(array_shift($path));

return sprintf('json_value(%s, \'$.%s\')', $field, collect($path)->map(function ($part) {
return '"'.$part.'"';
})->implode('.'));
}

/**
Expand Down
15 changes: 15 additions & 0 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2046,6 +2046,21 @@ public function testPostgresWrappingJson()
$this->assertEquals('select * from "users" where "items"->\'price\'->>\'in_usd\' = ? and "items"->>\'age\' = ?', $builder->toSql());
}

public function testSqlServerWrappingJson()
{
$builder = $this->getSqlServerBuilder();
$builder->select('items->price')->from('users')->where('items->price', '=', 1)->orderBy('items->price');
$this->assertEquals('select json_value([items], \'$."price"\') from [users] where json_value([items], \'$."price"\') = ? order by json_value([items], \'$."price"\') asc', $builder->toSql());

$builder = $this->getSqlServerBuilder();
$builder->select('*')->from('users')->where('items->price->in_usd', '=', 1);
$this->assertEquals('select * from [users] where json_value([items], \'$."price"."in_usd"\') = ?', $builder->toSql());

$builder = $this->getSqlServerBuilder();
$builder->select('*')->from('users')->where('items->price->in_usd', '=', 1)->where('items->age', '=', 2);
$this->assertEquals('select * from [users] where json_value([items], \'$."price"."in_usd"\') = ? and json_value([items], \'$."age"\') = ?', $builder->toSql());
}

public function testSQLiteOrderBy()
{
$builder = $this->getSQLiteBuilder();
Expand Down

0 comments on commit a8def08

Please sign in to comment.