diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index 86c705fedd98..46fae45a02d0 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -682,6 +682,17 @@ protected function compileJsonLength($column, $operator, $value) throw new RuntimeException('This database engine does not support JSON length operations.'); } + /** + * Compile a "JSON value cast" statement into SQL. + * + * @param string $value + * @return string + */ + public function compileJsonValueCast($value) + { + return $value; + } + /** * Compile a "where fulltext" clause. * diff --git a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php index 7586ce825bf4..3e4f06a20bef 100755 --- a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php @@ -128,6 +128,17 @@ protected function compileJsonLength($column, $operator, $value) return 'json_length('.$field.$path.') '.$operator.' '.$value; } + /** + * Compile a "JSON value cast" statement into SQL. + * + * @param string $value + * @return string + */ + public function compileJsonValueCast($value) + { + return 'cast('.$value.' as json)'; + } + /** * Compile the random statement into SQL. * diff --git a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php index a26157ea84a3..97dff1aa52bd 100755 --- a/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php @@ -205,6 +205,17 @@ protected function compileJsonLength($column, $operator, $value) return '(select count(*) from openjson('.$field.$path.')) '.$operator.' '.$value; } + /** + * Compile a "JSON value cast" statement into SQL. + * + * @param string $value + * @return string + */ + public function compileJsonValueCast($value) + { + return 'json_query('.$value.')'; + } + /** * Compile a single having clause. * diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php index 95a155c95b45..7041d22606ca 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php @@ -180,7 +180,9 @@ public function castAsJson($value) $value = DB::connection()->getPdo()->quote($value); - return DB::raw("CAST($value AS JSON)"); + return DB::raw( + DB::connection()->getQueryGrammar()->compileJsonValueCast($value) + ); } /** diff --git a/tests/Testing/Concerns/InteractsWithDatabaseTest.php b/tests/Testing/Concerns/InteractsWithDatabaseTest.php new file mode 100644 index 000000000000..750203d2d891 --- /dev/null +++ b/tests/Testing/Concerns/InteractsWithDatabaseTest.php @@ -0,0 +1,145 @@ +assertEquals(<<<'TEXT' + '["foo","bar"]' + TEXT, + $this->castAsJson(['foo', 'bar'], $grammar) + ); + + $this->assertEquals(<<<'TEXT' + '["foo","bar"]' + TEXT, + $this->castAsJson(collect(['foo', 'bar']), $grammar) + ); + + $this->assertEquals(<<<'TEXT' + '{"foo":"bar"}' + TEXT, + $this->castAsJson((object) ['foo' => 'bar'], $grammar) + ); + } + + public function testCastToJsonPostgres() + { + $grammar = new PostgresGrammar(); + + $this->assertEquals(<<<'TEXT' + '["foo","bar"]' + TEXT, + $this->castAsJson(['foo', 'bar'], $grammar) + ); + + $this->assertEquals(<<<'TEXT' + '["foo","bar"]' + TEXT, + $this->castAsJson(collect(['foo', 'bar']), $grammar) + ); + + $this->assertEquals(<<<'TEXT' + '{"foo":"bar"}' + TEXT, + $this->castAsJson((object) ['foo' => 'bar'], $grammar) + ); + } + + public function testCastToJsonSqlServer() + { + $grammar = new SqlServerGrammar(); + + $this->assertEquals(<<<'TEXT' + json_query('["foo","bar"]') + TEXT, + $this->castAsJson(['foo', 'bar'], $grammar) + ); + + $this->assertEquals(<<<'TEXT' + json_query('["foo","bar"]') + TEXT, + $this->castAsJson(collect(['foo', 'bar']), $grammar) + ); + + $this->assertEquals(<<<'TEXT' + json_query('{"foo":"bar"}') + TEXT, + $this->castAsJson((object) ['foo' => 'bar'], $grammar) + ); + } + + public function testCastToJsonMySql() + { + $grammar = new MySqlGrammar(); + + $this->assertEquals(<<<'TEXT' + cast('["foo","bar"]' as json) + TEXT, + $this->castAsJson(['foo', 'bar'], $grammar) + ); + + $this->assertEquals(<<<'TEXT' + cast('["foo","bar"]' as json) + TEXT, + $this->castAsJson(collect(['foo', 'bar']), $grammar) + ); + + $this->assertEquals(<<<'TEXT' + cast('{"foo":"bar"}' as json) + TEXT, + $this->castAsJson((object) ['foo' => 'bar'], $grammar) + ); + } + + protected function castAsJson($value, $grammar) + { + $connection = m::mock(ConnectionInterface::class); + + $connection->shouldReceive('getQueryGrammar')->andReturn($grammar); + + $connection->shouldReceive('getPdo->quote')->andReturnUsing(function ($value) { + return "'".$value."'"; + }); + + DB::shouldReceive('connection')->andReturn($connection); + + DB::shouldReceive('raw')->andReturnUsing(function ($value) { + return new Expression($value); + }); + + $instance = new class + { + use InteractsWithDatabase; + }; + + return $instance->castAsJson($value)->getValue(); + } +}