Fix database about boolean types for where in the json type (#5421)

This commit is contained in:
宣言就是Siam 2023-02-17 17:32:20 +08:00 committed by GitHub
parent 32becc3777
commit 3bbbfbd2eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 4 deletions

View File

@ -15,6 +15,7 @@
- [#5405](https://github.com/hyperf/hyperf/pull/5405) Fixed get local ip error when IPv6 exists.
- [#5417](https://github.com/hyperf/hyperf/pull/5417) Fixed bug that database-pgsql does not support migration.
- [#5421](https://github.com/hyperf/hyperf/pull/5421) Fixed database about boolean types for where in the json type
## Optimized

View File

@ -652,18 +652,22 @@ class Builder
return $this->whereNull($column, $boolean, $operator !== '=');
}
$type = 'Basic';
// If the column is making a JSON reference we'll check to see if the value
// is a boolean. If it is, we'll add the raw boolean string as an actual
// value to the query to ensure this is properly handled by the query.
if (Str::contains((string) $column, '->') && is_bool($value)) {
$value = new Expression($value ? 'true' : 'false');
if (is_string($column)) {
$type = 'JsonBoolean';
}
}
// Now that we are working with just a simple query we can put the elements
// in our array and add the query binding to our array of bindings that
// will be bound to each SQL statements when it is finally executed.
$type = 'Basic';
$this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean');
if (! $value instanceof Expression) {

View File

@ -461,6 +461,44 @@ class Grammar extends BaseGrammar
return $this->wrap($where['column']) . ' ' . $where['operator'] . ' ' . $value;
}
/**
* Compile a "where JSON boolean" clause.
*
* @param string $value
* @param array $where
* @return string
*/
protected function whereJsonBoolean(Builder $query, $where)
{
$column = $this->wrapJsonBooleanSelector($where['column']);
$value = $this->wrapJsonBooleanValue(
$this->parameter($where['value'])
);
return $column . ' ' . $where['operator'] . ' ' . $value;
}
/**
* Wrap the given JSON selector for boolean values.
*
* @param string $value
* @return string
*/
protected function wrapJsonBooleanSelector($value)
{
return $this->wrapJsonSelector($value);
}
/**
* Wrap the given JSON boolean value.
* @param mixed $value
*/
protected function wrapJsonBooleanValue($value)
{
return $value;
}
/**
* Compile a "where in" clause.
*

View File

@ -304,4 +304,17 @@ class MySqlGrammar extends Grammar
return 'json_unquote(json_extract(' . $field . $path . '))';
}
/**
* Wrap the given JSON selector for boolean values.
*
* @param string $value
* @return string
*/
protected function wrapJsonBooleanSelector($value)
{
[$field, $path] = $this->wrapJsonFieldAndPath($value);
return 'json_extract(' . $field . $path . ')';
}
}

View File

@ -2192,14 +2192,14 @@ class QueryBuilderTest extends TestCase
{
$builder = $this->getMySqlBuilder();
$builder->select('*')->from('users')->where('items->available', '=', true);
$this->assertEquals('select * from `users` where json_unquote(json_extract(`items`, \'$."available"\')) = true', $builder->toSql());
$this->assertEquals('select * from `users` where 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_unquote(json_extract(`items`, \'$."available"\')) = true and json_unquote(json_extract(`items`, \'$."active"\')) = false and json_unquote(json_extract(`items`, \'$."number_available"\')) = ?', $builder->toSql());
$this->assertEquals('select * from `users` where json_extract(`items`, \'$."available"\') = true and json_extract(`items`, \'$."active"\') = false and json_unquote(json_extract(`items`, \'$."number_available"\')) = ?', $builder->toSql());
}
public function testMySqlWrappingJson()