From a8def085091d9390205f0d4561cebea5bf6783ef Mon Sep 17 00:00:00 2001 From: Jonas Staudenmeir Date: Thu, 31 May 2018 16:20:02 +0200 Subject: [PATCH] Add JSON SELECT queries to SQL Server --- .../Query/Grammars/SqlServerGrammar.php | 31 ++++++++++++++++++- tests/Database/DatabaseQueryBuilderTest.php | 15 +++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php index dfefda3a22a3..dc1364e4cfe4 100755 --- a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php @@ -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 @@ -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('.')); } /** diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 01dcc81527d1..18c760fd1196 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -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();