Skip to content

Commit

Permalink
Add support JSON columns MariaDb.
Browse files Browse the repository at this point in the history
  • Loading branch information
terabytesoftw committed May 29, 2024
1 parent c6145cb commit 04b9708
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
2 changes: 1 addition & 1 deletion framework/db/mysql/JsonExpressionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ public function build(ExpressionInterface $expression, array &$params = [])
$placeholder = static::PARAM_PREFIX . count($params);
$params[$placeholder] = Json::encode($value);

return "CAST($placeholder AS JSON)";
return $placeholder;
}
}
25 changes: 25 additions & 0 deletions framework/db/mysql/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,19 @@ protected function findColumns($table)
}
throw $e;
}


$jsonColumns = $this->getJsonColumns($table);

foreach ($columns as $info) {
if ($this->db->slavePdo->getAttribute(\PDO::ATTR_CASE) !== \PDO::CASE_LOWER) {
$info = array_change_key_case($info, CASE_LOWER);
}

if (\in_array($info['field'], $jsonColumns, true)) {
$info['type'] = static::TYPE_JSON;
}

$column = $this->loadColumnSchema($info);
$table->columns[$column->name] = $column;
if ($column->isPrimaryKey) {
Expand Down Expand Up @@ -641,4 +650,20 @@ private function loadTableConstraints($tableName, $returnType)

return $result[$returnType];
}

private function getJsonColumns(TableSchema $table): array
{
$sql = $this->getCreateTableSql($table);
$result = [];

$regexp = '/json_valid\([\`"](.+)[\`"]\s*\)/mi';

if (\preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$result[] = $match[1];
}
}

return $result;
}
}
20 changes: 10 additions & 10 deletions tests/framework/db/mysql/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,35 +267,35 @@ public function conditionProvider()
// json conditions
[
['=', 'jsoncol', new JsonExpression(['lang' => 'uk', 'country' => 'UA'])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '{"lang":"uk","country":"UA"}'],
'[[jsoncol]] = :qp0', [':qp0' => '{"lang":"uk","country":"UA"}'],
],
[
['=', 'jsoncol', new JsonExpression([false])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '[false]']
'[[jsoncol]] = :qp0', [':qp0' => '[false]']
],
'object with type. Type is ignored for MySQL' => [
['=', 'prices', new JsonExpression(['seeds' => 15, 'apples' => 25], 'jsonb')],
'[[prices]] = CAST(:qp0 AS JSON)', [':qp0' => '{"seeds":15,"apples":25}'],
'[[prices]] = :qp0', [':qp0' => '{"seeds":15,"apples":25}'],
],
'nested json' => [
['=', 'data', new JsonExpression(['user' => ['login' => 'silverfire', 'password' => 'c4ny0ur34d17?'], 'props' => ['mood' => 'good']])],
'[[data]] = CAST(:qp0 AS JSON)', [':qp0' => '{"user":{"login":"silverfire","password":"c4ny0ur34d17?"},"props":{"mood":"good"}}']
'[[data]] = :qp0', [':qp0' => '{"user":{"login":"silverfire","password":"c4ny0ur34d17?"},"props":{"mood":"good"}}']
],
'null value' => [
['=', 'jsoncol', new JsonExpression(null)],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => 'null']
'[[jsoncol]] = :qp0', [':qp0' => 'null']
],
'null as array value' => [
['=', 'jsoncol', new JsonExpression([null])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '[null]']
'[[jsoncol]] = :qp0', [':qp0' => '[null]']
],
'null as object value' => [
['=', 'jsoncol', new JsonExpression(['nil' => null])],
'[[jsoncol]] = CAST(:qp0 AS JSON)', [':qp0' => '{"nil":null}']
'[[jsoncol]] = :qp0', [':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}']
'[[jsoncol]] = :qp0', [':qp0' => '{"a":1,"b":2}']
],
'query' => [
['=', 'jsoncol', new JsonExpression((new Query())->select('params')->from('user')->where(['id' => 1]))],
Expand All @@ -307,7 +307,7 @@ public function conditionProvider()
],
'nested and combined json expression' => [
['=', 'jsoncol', new JsonExpression(new JsonExpression(['a' => 1, 'b' => 2, 'd' => new JsonExpression(['e' => 3])]))],
"[[jsoncol]] = CAST(:qp0 AS JSON)", [':qp0' => '{"a":1,"b":2,"d":{"e":3}}']
"[[jsoncol]] = :qp0", [':qp0' => '{"a":1,"b":2,"d":{"e":3}}']
],
'search by property in JSON column (issue #15838)' => [
['=', new Expression("(jsoncol->>'$.someKey')"), '42'],
Expand All @@ -328,7 +328,7 @@ public function updateProvider()
[
'id' => 1,
],
$this->replaceQuotes('UPDATE [[profile]] SET [[description]]=CAST(:qp0 AS JSON) WHERE [[id]]=:qp1'),
$this->replaceQuotes('UPDATE [[profile]] SET [[description]]=:qp0 WHERE [[id]]=:qp1'),
[
':qp0' => '{"abc":"def","0":123,"1":null}',
':qp1' => 1,
Expand Down

0 comments on commit 04b9708

Please sign in to comment.