forked from doctrine/dbal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MariaDb1043Platform. New MariaDbPlatform using JSON as json column type.
MariaDb aliases columns specified as JSON to LONGTEXT. Since version 10.4.3, MariaDb adds a CHECK constraint to JSON columns to ensure they contain valid JSON and sets the column collation to utf8mb4_bin. Simply setting JSON as the column type in the platform results in introspection failures as the database reports LONGTEXT (not JSON) with changed collation. Therefore, inverse the aliasing where the relevant check constraint exists and ignore collation changes for JSON columns in the relevant database versions. The modified methods are MariaDBPlatform->getListTableColumnsSQL() and MySQLSchemaManager->selectTableColumns() The changes have been implemented in the MariaDBPlatform (guarded by a check for JSON as column type so they do not affect MariaDB1027Platform) and MySQLSchemaManager (guarded by a platform test). It ought to be possible to push most of the platform changes into the MySQLPlatform given the SQL query changes are guarded by MariaDB specific executable comments and so should be a no op for MySQL. Doing so would allow getDatabaseNameSQL() to be kept private. However, because the changes are entirely MariaDb specific they have been made in the MariaDBPlatform (this is also consistent with the plan to separate MariaDb and MySQL platforms). MariaDb1043Platform extends MariaDb1027Platform rather than MariaDBPlatform to ensure the platform checks in MySQLSchemaManager (based on MariaDb1027Platform) continue to work as expected. The alternative approach of adding the CHECK constraint to the SQL for the column is not robust as MariaDb syntax seems to require the CHECK constraint to be the final part of the column declaration and it was not obvious how to guarantee this (specifically, appending the CHECK constraint to the output of getJsonTypeDeclarationSQL() did not work). New public methods: MariaDBPlatform->getInverseJsonToLongtextAliasSQL() generates SQL snippets to inverse the JSON to LONGTEXT aliasing for JSON-specified columns. It is marked public because it is used in MySQLSchemaManager. Overridden methods: MariaDb1043Platform->getJsonTypeDeclarationSQL(). To return JSON. MariaDBPlatform->getListTableColumnsSQL(). To reverse the JSON to LONGTEXT aliasing carried out by MariaDb. MariaDBPlatform->MariaDBColumnToArray(). To unset collation and charset in column array (so parent needed to be marked protected). New test cases: 1. Types/JsonTest. Test storage and retrieval of json data. 2. Platforms/MariaDb1043PlatformTest. A clone of MariaDb1027Platform test. 3. Schema/MySQLSchemaManagerTest->testColumnIntrospection(). Ensures introspected table matches original table. Tests all doctrine types not just json. Based on failure highlighted in pull request doctrine#5100. For previous discussion on this topic, see: doctrine#5100 doctrine#3202 Further background at: https://mariadb.com/kb/en/json-data-type/ https://mariadb.com/kb/en/information-schema-check_constraints-table/ https://jira.mariadb.org/browse/MDEV-13916
- Loading branch information
Showing
8 changed files
with
286 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
namespace Doctrine\DBAL\Platforms; | ||
|
||
/** | ||
* Provides the behavior, features and SQL dialect of the MariaDB 10.4 (10.4.6 GA) database platform. | ||
* | ||
* Extend deprecated MariaDb1027Platform to ensure correct functions used in MySQLSchemaManager which | ||
* tests for MariaDb1027Platform not MariaDBPlatform. | ||
* | ||
* Note: Should not be used with versions prior to 10.4.3 when the 'native' JSON type was added. Since | ||
* it is not a true native type, do not override hasNativeJsonType() so the DC2Type comment will still | ||
* be set. | ||
*/ | ||
class MariaDb1043Platform extends MariaDb1027Platform | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getJsonTypeDeclarationSQL(array $column): string | ||
{ | ||
return 'JSON'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Doctrine\DBAL\Tests\Functional\Types; | ||
|
||
use Doctrine\DBAL\ParameterType; | ||
use Doctrine\DBAL\Schema\Table; | ||
use Doctrine\DBAL\Tests\FunctionalTestCase; | ||
use Doctrine\DBAL\Types\Type; | ||
|
||
use function json_decode; | ||
|
||
class JsonTest extends FunctionalTestCase | ||
{ | ||
protected function setUp(): void | ||
{ | ||
$table = new Table('json_table'); | ||
$table->addColumn('id', 'integer'); | ||
|
||
$table->addColumn('val', 'json'); | ||
$table->setPrimaryKey(['id']); | ||
|
||
$this->dropAndCreateTable($table); | ||
} | ||
|
||
public function testInsertAndSelect(): void | ||
{ | ||
$id1 = 1; | ||
$id2 = 2; | ||
|
||
$value1 = [ | ||
'firstKey' => 'firstVal', | ||
'secondKey' => 'secondVal', | ||
'nestedKey' => [ | ||
'nestedKey1' => 'nestedVal1', | ||
'nestedKey2' => 2, | ||
], | ||
]; | ||
$value2 = json_decode('{"key1":"Val1","key2":2,"key3":"Val3"}', true); | ||
|
||
$this->insert($id1, $value1); | ||
$this->insert($id2, $value2); | ||
|
||
self::assertSame($value1, $this->select($id1)); | ||
self::assertSame($value2, $this->select($id2)); | ||
} | ||
|
||
/** @param array{int|string, scalar|array{int|string, scalar}}[] $value */ | ||
private function insert(int $id, array $value): void | ||
{ | ||
$result = $this->connection->insert('json_table', [ | ||
'id' => $id, | ||
'val' => $value, | ||
], [ | ||
ParameterType::INTEGER, | ||
Type::getType('json'), | ||
]); | ||
|
||
self::assertSame(1, $result); | ||
} | ||
|
||
/** @return array{int|string, scalar|array{int|string, scalar}}[] $value */ | ||
private function select(int $id): array | ||
{ | ||
$value = $this->connection->fetchOne( | ||
'SELECT val FROM json_table WHERE id = ?', | ||
[$id], | ||
[ParameterType::INTEGER], | ||
); | ||
|
||
self::assertIsString($value); | ||
|
||
$value = json_decode($value, true); | ||
|
||
self::assertIsArray($value); | ||
|
||
return $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
namespace Doctrine\DBAL\Tests\Platforms; | ||
|
||
use Doctrine\DBAL\Platforms\AbstractPlatform; | ||
use Doctrine\DBAL\Platforms\MariaDb1043Platform; | ||
use Doctrine\DBAL\Types\Types; | ||
|
||
class MariaDb1043PlatformTest extends AbstractMySQLPlatformTestCase | ||
{ | ||
public function createPlatform(): AbstractPlatform | ||
{ | ||
return new MariaDb1043Platform(); | ||
} | ||
|
||
public function testHasNativeJsonType(): void | ||
{ | ||
self::assertFalse($this->platform->hasNativeJsonType()); | ||
} | ||
|
||
/** | ||
* From MariaDB 10.2.7, JSON type is an alias to LONGTEXT however from 10.4.3 setting a column | ||
* as JSON adds additional functionality so use JSON. | ||
* | ||
* @link https://mariadb.com/kb/en/library/json-data-type/ | ||
*/ | ||
public function testReturnsJsonTypeDeclarationSQL(): void | ||
{ | ||
self::assertSame('JSON', $this->platform->getJsonTypeDeclarationSQL([])); | ||
} | ||
|
||
public function testInitializesJsonTypeMapping(): void | ||
{ | ||
self::assertTrue($this->platform->hasDoctrineTypeMappingFor('json')); | ||
self::assertSame(Types::JSON, $this->platform->getDoctrineTypeMapping('json')); | ||
} | ||
|
||
public function testIgnoresDifferenceInDefaultValuesForUnsupportedColumnTypes(): void | ||
{ | ||
self::markTestSkipped('MariaDb1043Platform supports default values for BLOB and TEXT columns'); | ||
} | ||
} |