Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5916 from cgknx/native-mariadb-json
Use Native JSON type instead of LONGTEXT for MariaDB
- Loading branch information
Showing
13 changed files
with
590 additions
and
6 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,114 @@ | ||
<?php | ||
|
||
namespace Doctrine\DBAL\Platforms; | ||
|
||
use Doctrine\DBAL\Types\JsonType; | ||
|
||
use function sprintf; | ||
|
||
/** | ||
* 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. | ||
*/ | ||
class MariaDb1043Platform extends MariaDb1027Platform | ||
{ | ||
/** | ||
* Use JSON rather than LONGTEXT for json columns. Since it is not a true native type, do not override | ||
* hasNativeJsonType() so the DC2Type comment will still be set. | ||
* | ||
* {@inheritdoc} | ||
*/ | ||
public function getJsonTypeDeclarationSQL(array $column): string | ||
{ | ||
return 'JSON'; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* From version 10.4.3, MariaDb aliases JSON to LONGTEXT and adds a constraint CHECK (json_valid). Reverse | ||
* this process when introspecting tables. | ||
* | ||
* @see https://mariadb.com/kb/en/information-schema-check_constraints-table/ | ||
* @see https://mariadb.com/kb/en/json-data-type/ | ||
* @see https://jira.mariadb.org/browse/MDEV-13916 | ||
*/ | ||
public function getListTableColumnsSQL($table, $database = null): string | ||
{ | ||
[$columnTypeSQL, $joinCheckConstraintSQL] = $this->getColumnTypeSQLSnippets(); | ||
|
||
return sprintf( | ||
<<<SQL | ||
SELECT c.COLUMN_NAME AS Field, | ||
$columnTypeSQL AS Type, | ||
c.IS_NULLABLE AS `Null`, | ||
c.COLUMN_KEY AS `Key`, | ||
c.COLUMN_DEFAULT AS `Default`, | ||
c.EXTRA AS Extra, | ||
c.COLUMN_COMMENT AS Comment, | ||
c.CHARACTER_SET_NAME AS CharacterSet, | ||
c.COLLATION_NAME AS Collation | ||
FROM information_schema.COLUMNS c | ||
$joinCheckConstraintSQL | ||
WHERE c.TABLE_SCHEMA = %s | ||
AND c.TABLE_NAME = %s | ||
ORDER BY ORDINAL_POSITION ASC; | ||
SQL | ||
, | ||
$this->getDatabaseNameSQL($database), | ||
$this->quoteStringLiteral($table), | ||
); | ||
} | ||
|
||
/** | ||
* Generate SQL snippets to reverse the aliasing of JSON to LONGTEXT. | ||
* | ||
* MariaDb aliases columns specified as JSON to LONGTEXT and sets a CHECK constraint to ensure the column | ||
* is valid json. This function generates the SQL snippets which reverse this aliasing i.e. report a column | ||
* as JSON where it was originally specified as such instead of LONGTEXT. | ||
* | ||
* The CHECK constraints are stored in information_schema.CHECK_CONSTRAINTS so JOIN that table. | ||
* | ||
* @return array{string, string} | ||
*/ | ||
public function getColumnTypeSQLSnippets(string $tableAlias = 'c'): array | ||
{ | ||
if ($this->getJsonTypeDeclarationSQL([]) !== 'JSON') { | ||
return parent::getColumnTypeSQLSnippets($tableAlias); | ||
} | ||
|
||
$columnTypeSQL = <<<SQL | ||
IF( | ||
x.CHECK_CLAUSE IS NOT NULL AND $tableAlias.COLUMN_TYPE = 'longtext', | ||
'json', | ||
$tableAlias.COLUMN_TYPE | ||
) | ||
SQL; | ||
|
||
$joinCheckConstraintSQL = <<<SQL | ||
LEFT JOIN information_schema.CHECK_CONSTRAINTS x | ||
ON ( | ||
$tableAlias.TABLE_SCHEMA = x.CONSTRAINT_SCHEMA | ||
AND $tableAlias.TABLE_NAME = x.TABLE_NAME | ||
AND x.CHECK_CLAUSE = CONCAT('json_valid(`', $tableAlias.COLUMN_NAME , '`)') | ||
) | ||
SQL; | ||
|
||
return [$columnTypeSQL, $joinCheckConstraintSQL]; | ||
} | ||
|
||
/** {@inheritDoc} */ | ||
public function getColumnDeclarationSQL($name, array $column) | ||
{ | ||
// MariaDb forces column collation to utf8mb4_bin where the column was declared as JSON so ignore | ||
// collation and character set for json columns as attempting to set them can cause an error. | ||
if ($this->getJsonTypeDeclarationSQL([]) === 'JSON' && ($column['type'] ?? null) instanceof JsonType) { | ||
unset($column['collation']); | ||
unset($column['charset']); | ||
} | ||
|
||
return parent::getColumnDeclarationSQL($name, $column); | ||
} | ||
} |
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
Oops, something went wrong.