Browse Source

Fixed JsonExpressionBuilder to cast JSON explicitly

Fixes #15839;
tags/2.0.14.2
SilverFire - Dmitry Naumenko 7 years ago
parent
commit
cc29ef8968
No known key found for this signature in database
GPG Key ID: 39DD917A92B270A
  1. 1
      framework/CHANGELOG.md
  2. 5
      framework/db/mysql/JsonExpressionBuilder.php
  3. 37
      tests/framework/db/mysql/QueryBuilderTest.php

1
framework/CHANGELOG.md

@ -16,6 +16,7 @@ Yii Framework 2 Change Log
- Bug: Fixed table schema retrieving for PostgreSQL when the table name was wrapped in quotes (silverfire)
- Bug #15776: Fixed slow MySQL constraints retrieving (MartijnHols, berosoboy, sergeymakinen)
- Bug #15836: Fixed nesting of `yii\db\ArrayExpresiion`, `yii\db\JsonExpression` (silverfire)
- Bug #15839: Fixed `yii\db\mysql\JsonExpressionBuilder` to cast JSON explicitly (silverfire)

5
framework/db/mysql/JsonExpressionBuilder.php

@ -34,6 +34,9 @@ class JsonExpressionBuilder implements ExpressionBuilderInterface
public function build(ExpressionInterface $expression, array &$params = [])
{
$value = $expression->getValue();
if ($value === null) {
return 'NULL';
}
if ($value instanceof Query) {
list ($sql, $params) = $this->queryBuilder->build($value, $params);
@ -43,6 +46,6 @@ class JsonExpressionBuilder implements ExpressionBuilderInterface
$placeholder = static::PARAM_PREFIX . count($params);
$params[$placeholder] = Json::encode($value);
return $placeholder;
return "CAST($placeholder AS JSON)";
}
}

37
tests/framework/db/mysql/QueryBuilderTest.php

@ -187,21 +187,38 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
{
return array_merge(parent::conditionProvider(), [
// json conditions
[['=', 'jsoncol', new JsonExpression(['lang' => 'uk', 'country' => 'UA'])], '[[jsoncol]] = :qp0', [':qp0' => '{"lang":"uk","country":"UA"}']],
[['=', 'jsoncol', new JsonExpression([false])], '[[jsoncol]] = :qp0', [':qp0' => '[false]']],
[
['=', 'jsoncol', new JsonExpression(['lang' => 'uk', 'country' => 'UA'])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '{"lang":"uk","country":"UA"}'],
],
[
['=', 'jsoncol', new JsonExpression([false])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '[false]']
],
'object with type. Type is ignored for MySQL' => [
['=', 'prices', new JsonExpression(['seeds' => 15, 'apples' => 25], 'jsonb')],
'[[prices]] = :qp0', [':qp0' => '{"seeds":15,"apples":25}']
'[[prices]] = CAST(:qp0 AS JSON)', [':qp0' => '{"seeds":15,"apples":25}'],
],
'nested json' => [
['=', 'data', new JsonExpression(['user' => ['login' => 'silverfire', 'password' => 'c4ny0ur34d17?'], 'props' => ['mood' => 'good']])],
'[[data]] = :qp0', [':qp0' => '{"user":{"login":"silverfire","password":"c4ny0ur34d17?"},"props":{"mood":"good"}}']
'[[data]] = CAST(:qp0 AS JSON)', [':qp0' => '{"user":{"login":"silverfire","password":"c4ny0ur34d17?"},"props":{"mood":"good"}}']
],
'null value' => [
['=', 'jsoncol', new JsonExpression(null)],
'[[jsoncol]] = NULL', []
],
'null as array value' => [
['=', 'jsoncol', new JsonExpression([null])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '[null]']
],
'null as object value' => [
['=', 'jsoncol', new JsonExpression(['nil' => null])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '{"nil":null}']
],
'with object as value' => [
['=', 'jsoncol', new JsonExpression(new DynamicModel(['a' => 1, 'b' => 2]))],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '{"a":1,"b":2}']
],
'null value' => [['=', 'jsoncol', new JsonExpression(null)], '[[jsoncol]] = :qp0', [':qp0' => 'null']],
'null as array value' => [['=', 'jsoncol', new JsonExpression([null])], '[[jsoncol]] = :qp0', [':qp0' => '[null]']],
'null as object value' => [['=', 'jsoncol', new JsonExpression(['nil' => null])], '[[jsoncol[[ = :qp0', [':qp0' => '{"nil":null}']],
[['=', 'jsoncol', new JsonExpression(new DynamicModel(['a' => 1, 'b' => 2]))], '[[jsoncol]] = :qp0', [':qp0' => '{"a":1,"b":2}']],
'query' => [
['=', 'jsoncol', new JsonExpression((new Query())->select('params')->from('user')->where(['id' => 1]))],
'[[jsoncol]] = (SELECT [[params]] FROM [[user]] WHERE [[id]]=:qp0)', [':qp0' => 1]
@ -212,7 +229,7 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
],
'nested and combined json expression' => [
['=', 'jsoncol', new JsonExpression(new JsonExpression(['a' => 1, 'b' => 2, 'd' => new JsonExpression(['e' => 3])]))],
"[[jsoncol]] = :qp0", [':qp0' => '{"a":1,"b":2,"d":{"e":3}}']
"[[jsoncol]] = CAST(:qp0 AS JSON)", [':qp0' => '{"a":1,"b":2,"d":{"e":3}}']
],
'search by property in JSON column (issue #15838)' => [
['=', new Expression("(jsoncol->>'$.someKey')"), '42'],

Loading…
Cancel
Save