| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- <?php
- namespace PhpDevCommunity\PaperORM\Platform;
- use LogicException;
- use PhpDevCommunity\PaperORM\Mapping\Column\AnyColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\AutoIncrementColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\BinaryColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\BoolColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\Column;
- use PhpDevCommunity\PaperORM\Mapping\Column\DateColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\DateTimeColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\DecimalColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\FloatColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\IntColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\JoinColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\JsonColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\PrimaryKeyColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\SlugColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\StringColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\TextColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\TimestampColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\TokenColumn;
- use PhpDevCommunity\PaperORM\Mapping\Column\UuidColumn;
- use PhpDevCommunity\PaperORM\Metadata\ColumnMetadata;
- use PhpDevCommunity\PaperORM\Metadata\ForeignKeyMetadata;
- use PhpDevCommunity\PaperORM\Metadata\IndexMetadata;
- use PhpDevCommunity\PaperORM\PaperConnection;
- use PhpDevCommunity\PaperORM\Parser\SQLTypeParser;
- use PhpDevCommunity\PaperORM\Schema\MariaDBSchema;
- use PhpDevCommunity\PaperORM\Schema\SchemaInterface;
- class MariaDBPlatform extends AbstractPlatform
- {
- private PaperConnection $connection;
- private MariaDBSchema $schema;
- public function __construct(PaperConnection $connection, MariaDBSchema $schema)
- {
- $this->connection = $connection;
- $this->schema = $schema;
- }
- public function getDatabaseName(): string
- {
- return $this->connection->getParams()['path'] ?? '';
- }
- public function listTables(): array
- {
- $rows = $this->connection->fetchAll($this->schema->showTables());
- $tables = [];
- foreach ($rows as $table) {
- $table = array_values($table);
- $tables[] = $table[0];
- }
- rsort($tables, SORT_STRING);
- return $tables;
- }
- /**
- * @param string $tableName
- * @return array<ColumnMetadata>
- */
- public function listTableColumns(string $tableName): array
- {
- $tables = $this->listTables();
- if (!in_array($tableName, $tables)) {
- return [];
- }
- $rows = $this->connection->fetchAll($this->schema->showTableColumns($tableName));
- $foreignKeys = $this->connection->fetchAll($this->schema->showForeignKeys($tableName));
- $columns = [];
- foreach ($rows as $row) {
- $foreignKeyMetadata = null;
- foreach ($foreignKeys as $foreignKey) {
- if ($row['Field'] == $foreignKey['COLUMN_NAME']) {
- $foreignKeyMetadata = ForeignKeyMetadata::fromArray([
- 'name' => $foreignKey['CONSTRAINT_NAME'],
- 'columns' => [$row['Field']],
- 'referenceTable' => $foreignKey['REFERENCED_TABLE_NAME'],
- 'referenceColumns' => [$foreignKey['REFERENCED_COLUMN_NAME']],
- 'onDelete' => $this->convertForeignKeyRuleStringToCode($foreignKey['DELETE_RULE']),
- 'onUpdate' => $this->convertForeignKeyRuleStringToCode($foreignKey['UPDATE_RULE']),
- ]);
- break;
- }
- }
- $columnMetadata = ColumnMetadata::fromArray([
- 'name' => $row['Field'],
- 'type' => SQLTypeParser::getBaseType($row['Type']),
- 'primary' => ($row['Key'] === 'PRI'),
- 'foreignKeyMetadata' => $foreignKeyMetadata,
- 'null' => ($row['Null'] === 'YES'),
- 'default' => $row['Default'] ?? null,
- 'comment' => $row['comment'] ?? null,
- 'attributes' => SQLTypeParser::extractTypedParameters($row['Type']),
- ]);
- $columns[] = $columnMetadata;
- }
- return $columns;
- }
- /**
- * @param string $tableName
- * @return array<IndexMetadata>
- */
- public function listTableIndexes(string $tableName): array
- {
- $tables = $this->listTables();
- if (!in_array($tableName, $tables)) {
- return [];
- }
- $indexes = $this->connection->fetchAll($this->schema->showTableIndexes($tableName));
- $indexByColumns = [];
- foreach ($indexes as $index) {
- $indexName = $index['Key_name'];
- if (isset($indexByColumns[$indexName])) {
- $indexByColumns[$indexName]['columns'][] = $index['Column_name'];
- continue;
- }
- if ($indexName === 'PRIMARY') {
- continue;
- }
- $indexByColumns[$indexName] = [
- 'tableName' => $index['Table'],
- 'name' => $indexName,
- 'columns' => [$index['Column_name']],
- 'unique' => ((int)$index['Non_unique'] === 0),
- ];
- }
- $indexesFormatted = [];
- foreach ($indexByColumns as $idx) {
- $indexesFormatted[] = IndexMetadata::fromArray($idx);
- }
- return $indexesFormatted;
- }
- public function listDatabases(): array
- {
- throw new LogicException(sprintf("The method '%s' is not supported by the platform interface.", __METHOD__));
- }
- public function createDatabase(): void
- {
- $connection = $this->connection->cloneConnectionWithoutDbname();
- $connection->executeStatement($this->schema->createDatabase($this->getDatabaseName()));
- }
- public function createDatabaseIfNotExists(): void
- {
- $connection = $this->connection->cloneConnectionWithoutDbname();
- $connection->executeStatement($this->schema->createDatabaseIfNotExists($this->getDatabaseName()));
- }
- public function dropDatabase(): void
- {
- $connection = $this->connection->cloneConnectionWithoutDbname();
- $database = $this->getDatabaseName();
- $connection->executeStatement($this->schema->dropDatabase($database));
- }
- public function createTable(string $tableName, array $columns): int
- {
- return $this->executeStatement($this->schema->createTable($tableName, $this->mapColumnsToMetadata($tableName, $columns)));
- }
- public function createTableIfNotExists(string $tableName, array $columns, array $options = []): int
- {
- return $this->connection->executeStatement($this->schema->createTableIfNotExists($tableName, $this->mapColumnsToMetadata($tableName, $columns)));
- }
- public function dropTable(string $tableName): int
- {
- return $this->connection->executeStatement($this->schema->dropTable($tableName));
- }
- public function addColumn(string $tableName, Column $column): int
- {
- return $this->connection->executeStatement($this->schema->addColumn($tableName, $this->mapColumnToMetadata($tableName, $column)));
- }
- public function dropColumn(string $tableName, Column $column): int
- {
- return $this->connection->executeStatement($this->schema->dropColumn($tableName, $this->mapColumnToMetadata($tableName, $column)));
- }
- public function renameColumn(string $tableName, string $oldColumnName, string $newColumnName): int
- {
- return $this->connection->executeStatement($this->schema->renameColumn($tableName, $oldColumnName, $newColumnName));
- }
- public function createIndex(IndexMetadata $indexMetadata): int
- {
- return $this->connection->executeStatement($this->schema->createIndex($indexMetadata));
- }
- public function dropIndex(IndexMetadata $indexMetadata): int
- {
- return $this->connection->executeStatement($this->schema->dropIndex($indexMetadata));
- }
- public function createForeignKeyConstraint(string $tableName, ForeignKeyMetadata $foreignKey): int
- {
- return $this->executeStatement($this->schema->createForeignKeyConstraint($tableName, $foreignKey));
- }
- public function dropForeignKeyConstraints(string $tableName, string $foreignKeyName): int
- {
- return $this->executeStatement($this->schema->dropForeignKeyConstraints($tableName, $foreignKeyName));
- }
- public function getMaxLength(): int
- {
- return 30;
- }
- public function getPrefixIndexName(): string
- {
- return 'ix_';
- }
- public function getPrefixUniqIndexName(): string
- {
- return 'uniq_';
- }
- public function getPrefixForeignKeyName(): string
- {
- return 'fk_';
- }
- public function getColumnTypeMappings(): array
- {
- return [
- PrimaryKeyColumn::class => [
- 'type' => 'INT',
- 'args' => [11]
- ],
- IntColumn::class => [
- 'type' => 'INT',
- 'args' => [11]
- ],
- JoinColumn::class => [
- 'type' => 'INT',
- 'args' => [11]
- ],
- DecimalColumn::class => [
- 'type' => 'DECIMAL',
- 'args' => [10, 5]
- ],
- FloatColumn::class => [
- 'type' => 'FLOAT',
- 'args' => []
- ],
- DateColumn::class => [
- 'type' => 'DATE',
- 'args' => []
- ],
- DateTimeColumn::class => [
- 'type' => 'DATETIME',
- 'args' => []
- ],
- TimestampColumn::class => [
- 'type' => 'DATETIME',
- 'args' => [],
- ],
- BoolColumn::class => [
- 'type' => 'TINYINT',
- 'args' => [1]
- ],
- TextColumn::class => [
- 'type' => 'TEXT',
- 'args' => []
- ],
- JsonColumn::class => [
- 'type' => 'LONGTEXT',
- 'args' => []
- ],
- StringColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [255]
- ],
- SlugColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [128]
- ],
- BinaryColumn::class => [
- 'type' => 'BLOB',
- 'args' => []
- ],
- AnyColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [150],
- ],
- UuidColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [36],
- ],
- AutoIncrementColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [150],
- ],
- TokenColumn::class => [
- 'type' => 'VARCHAR',
- 'args' => [128],
- ]
- ];
- }
- public function convertForeignKeyRuleStringToCode(?string $rule): int
- {
- $rule = strtoupper($rule);
- switch ($rule) {
- case 'CASCADE':
- return ForeignKeyMetadata::CASCADE;
- case 'SET NULL':
- return ForeignKeyMetadata::SET_NULL;
- case 'RESTRICT':
- return ForeignKeyMetadata::RESTRICT;
- case 'NO ACTION': /* fall-through */
- default:
- return ForeignKeyMetadata::NO_ACTION;
- }
- }
- public function getSchema(): SchemaInterface
- {
- return $this->schema;
- }
- public function supportsTransactionalDDL(): bool
- {
- return false;
- }
- public function getConnection(): PaperConnection
- {
- return $this->connection;
- }
- public function executeStatement(string $sql): int
- {
- $result = 0;
- foreach (explode(';', $sql) as $stmt) {
- $stmt = trim($stmt);
- if (!empty($stmt)) {
- $result += $this->getConnection()->executeStatement($stmt);
- }
- }
- return $result;
- }
- public function autoCreateIndexJoinColumns(): bool
- {
- return true;
- }
- public function autoCreateIndexPrimaryKeys(): bool
- {
- return false;
- }
- public function autoCreateIndexUniqueColumns(): bool
- {
- return true;
- }
- }
|