@return string */ protected function handleTypeDecimal(BaseColumn $column): string { return 'DECIMAL'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeBoolean(BaseColumn $column): string { return 'BOOLEAN'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeBinary(BaseColumn $column): string { return 'BLOB'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeText(BaseColumn $column): string { return 'TEXT'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeString(BaseColumn $column): string { return 'VARCHAR(' . $this->value($column->get('length', 255)) . ')'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeFixed(BaseColumn $column): string { return 'CHAR(' . $this->value($column->get('length', 255)) . ')'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeTime(BaseColumn $column): string { return 'TIME'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeTimestamp(BaseColumn $column): string { return 'TIMESTAMP'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeDate(BaseColumn $column): string { return 'DATE'; } /** * @param BaseColumn $column * @return string */ protected function handleTypeDateTime(BaseColumn $column): string { return 'DATETIME'; } /** * @param BaseColumn $column * @return string */ protected function handleModifierUnsigned(BaseColumn $column): string { return $column->get('unsigned', \false) ? 'UNSIGNED' : ''; } /** * @param BaseColumn $column * @return string */ protected function handleModifierNullable(BaseColumn $column): string { if ($column->get('nullable', \true)) { return ''; } return 'NOT NULL'; } /** * @param BaseColumn $column * @return string */ protected function handleModifierDefault(BaseColumn $column): string { return null === $column->get('default') ? '' : 'DEFAULT ' . $this->value($column->get('default')); } /** * @param BaseColumn $column * @return string */ protected function handleModifierAutoincrement(BaseColumn $column): string { if ($column->getType() !== 'integer' || !in_array($column->get('size', 'normal'), $this->serials)) { return ''; } return $column->get('autoincrement', \false) ? $this->autoincrement : ''; } /** * @param CreateTable $schema * @return string */ protected function handlePrimaryKey(CreateTable $schema): string { if (null === $pk = $schema->getPrimaryKey()) { return ''; } return ",\n" . 'CONSTRAINT ' . $this->wrap($pk['name']) . ' PRIMARY KEY (' . $this->wrapArray($pk['columns']) . ')'; } /** * @param CreateTable $schema * @return string */ protected function handleUniqueKeys(CreateTable $schema): string { $indexes = $schema->getUniqueKeys(); if (empty($indexes)) { return ''; } $sql = []; foreach ($schema->getUniqueKeys() as $name => $columns) { $sql[] = 'CONSTRAINT ' . $this->wrap($name) . ' UNIQUE (' . $this->wrapArray($columns) . ')'; } return ",\n" . implode(",\n", $sql); } /** * @param CreateTable $schema * @return string[] */ protected function handleIndexKeys(CreateTable $schema): array { $indexes = $schema->getIndexes(); if (empty($indexes)) { return []; } $sql = []; $table = $this->wrap($schema->getTableName()); foreach ($indexes as $name => $columns) { $sql[] = 'CREATE INDEX ' . $this->wrap($name) . ' ON ' . $table . '(' . $this->wrapArray($columns) . ')'; } return $sql; } /** * @param CreateTable $schema * @return string */ protected function handleForeignKeys(CreateTable $schema): string { /** @var ForeignKey[] $keys */ $keys = $schema->getForeignKeys(); if (empty($keys)) { return ''; } $sql = []; foreach ($keys as $name => $key) { $cmd = 'CONSTRAINT ' . $this->wrap($name) . ' FOREIGN KEY (' . $this->wrapArray($key->getColumns()) . ') '; $cmd .= 'REFERENCES ' . $this->wrap($key->getReferencedTable()) . ' (' . $this->wrapArray($key->getReferencedColumns()) . ')'; foreach ($key->getActions() as $actionName => $action) { $cmd .= ' ' . $actionName . ' ' . $action; } $sql[] = $cmd; } return ",\n" . implode(",\n", $sql); } /** * @param CreateTable $schema * @return string */ protected function handleEngine(CreateTable $schema): string { if (null !== $engine = $schema->getEngine()) { return ' ENGINE = ' . strtoupper($engine); } return ''; } /** * Set the character set for the table. * * @param CreateTable $schema * @return string */ protected function handleCharacterSet(CreateTable $schema): string { global $wpdb; if ($wpdb) { return ' ' . $wpdb->get_charset_collate(); } return ''; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropPrimaryKey(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' DROP CONSTRAINT ' . $this->wrap($data); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropUniqueKey(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' DROP CONSTRAINT ' . $this->wrap($data); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropIndex(AlterTable $table, $data): string { return 'DROP INDEX ' . $this->wrap($table->getTableName()) . '.' . $this->wrap($data); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropForeignKey(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' DROP CONSTRAINT ' . $this->wrap($data); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropColumn(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' DROP COLUMN ' . $this->wrap($data); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleRenameColumn(AlterTable $table, $data): string { return ''; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleModifyColumn(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' MODIFY COLUMN ' . $this->handleColumns([$data]); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleAddColumn(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ADD COLUMN ' . $this->handleColumns([$data]); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleAddPrimary(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ADD CONSTRAINT ' . $this->wrap($data['name']) . ' PRIMARY KEY (' . $this->wrapArray($data['columns']) . ')'; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleAddUnique(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ADD CONSTRAINT ' . $this->wrap($data['name']) . ' UNIQUE (' . $this->wrapArray($data['columns']) . ')'; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleAddIndex(AlterTable $table, $data): string { return 'CREATE INDEX ' . $this->wrap($data['name']) . ' ON ' . $this->wrap($table->getTableName()) . ' (' . $this->wrapArray($data['columns']) . ')'; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleAddForeign(AlterTable $table, $data): string { /** @var ForeignKey $key */ $key = $data['foreign']; return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ADD CONSTRAINT ' . $this->wrap($data['name']) . ' FOREIGN KEY (' . $this->wrapArray($key->getColumns()) . ') ' . 'REFERENCES ' . $this->wrap($key->getReferencedTable()) . '(' . $this->wrapArray($key->getReferencedColumns()) . ')'; } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleSetDefaultValue(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ALTER COLUMN ' . $this->wrap($data['column']) . ' SET DEFAULT ' . $this->value($data['value']); } /** * @param AlterTable $table * @param mixed $data * @return string */ protected function handleDropDefaultValue(AlterTable $table, $data): string { return 'ALTER TABLE ' . $this->wrap($table->getTableName()) . ' ALTER COLUMN ' . $this->wrap($data) . ' DROP DEFAULT'; } /** * @return array */ public function getParams(): array { $params = $this->params; $this->params = []; return $params; } /** * @param string $dsn * @return array */ public function currentDatabase(string $dsn): array { return ['sql' => 'SELECT database()', 'params' => []]; } /** * @param string $current * @param string $new * @return array */ public function renameTable(string $current, string $new): array { return ['sql' => 'RENAME TABLE ' . $this->wrap($current) . ' TO ' . $this->wrap($new), 'params' => []]; } /** * @param string $database * @return array */ public function getTables(string $database): array { $sql = 'SELECT ' . $this->wrap('table_name') . ' FROM ' . $this->wrap('information_schema') . '.' . $this->wrap('tables') . ' WHERE table_type = ? AND table_schema = ? ORDER BY ' . $this->wrap('table_name') . ' ASC'; return ['sql' => $sql, 'params' => ['BASE TABLE', $database]]; } /** * @param string $database * @param string $table * @return array */ public function getColumns(string $database, string $table): array { $sql = 'SELECT ' . $this->wrap('column_name') . ' AS ' . $this->wrap('name') . ', ' . $this->wrap('column_type') . ' AS ' . $this->wrap('type') . ' FROM ' . $this->wrap('information_schema') . '.' . $this->wrap('columns') . ' WHERE ' . $this->wrap('table_schema') . ' = ? AND ' . $this->wrap('table_name') . ' = ? ' . ' ORDER BY ' . $this->wrap('ordinal_position') . ' ASC'; return ['sql' => $sql, 'params' => [$database, $table]]; } /** * @param CreateTable $schema * @return array */ public function create(CreateTable $schema): array { $sql = 'CREATE TABLE ' . $this->wrap($schema->getTableName()); $sql .= "(\n"; $sql .= $this->handleColumns($schema->getColumns()); $sql .= $this->handlePrimaryKey($schema); $sql .= $this->handleUniqueKeys($schema); $sql .= $this->handleForeignKeys($schema); $sql .= "\n)" . $this->handleEngine($schema) . $this->handleCharacterSet($schema); $commands = []; $commands[] = ['sql' => $sql, 'params' => $this->getParams()]; foreach ($this->handleIndexKeys($schema) as $index) { $commands[] = ['sql' => $index, 'params' => []]; } return $commands; } /** * @param AlterTable $schema * @return array */ public function alter(AlterTable $schema): array { $commands = []; foreach ($schema->getCommands() as $command) { $type = 'handle' . ucfirst($command['type']); $sql = $this->{$type}($schema, $command['data']); if ($sql === '') { continue; } $commands[] = ['sql' => $sql, 'params' => $this->getParams()]; } return $commands; } /** * @param string $table * @return array */ public function drop(string $table): array { return ['sql' => 'DROP TABLE ' . $this->wrap($table), 'params' => []]; } /** * @param string $table * @return array */ public function truncate(string $table): array { return ['sql' => 'TRUNCATE TABLE ' . $this->wrap($table), 'params' => []]; } }