修复seeder错误;删除第三方的think迁移工具,在extend中重新实现;

This commit is contained in:
2023-09-20 15:35:20 +08:00
parent 0b23e0a940
commit 85f2f29b81
91 changed files with 20798 additions and 66 deletions

View File

@@ -0,0 +1,412 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use Exception;
use InvalidArgumentException;
use Phinx\Db\Table;
use Phinx\Db\Table\Column;
use Phinx\Util\Literal;
use think\console\Input as InputInterface;
use think\migration\NullOutput;
use think\console\Output as OutputInterface;
/**
* Base Abstract Database Adapter.
*/
abstract class AbstractAdapter implements AdapterInterface
{
/**
* @var array<string, mixed>
*/
protected $options = [];
/**
* @var \think\console\Input|null
*/
protected $input;
/**
* @var \think\console\Output
*/
protected $output;
/**
* @var string[]
*/
protected $createdTables = [];
/**
* @var string
*/
protected $schemaTableName = 'phinxlog';
/**
* @var array
*/
protected $dataDomain = [];
/**
* Class Constructor.
*
* @param array<string, mixed> $options Options
* @param \think\console\Input|null $input Input Interface
* @param \think\console\Output|null $output Output Interface
*/
public function __construct(array $options, ?InputInterface $input = null, ?OutputInterface $output = null)
{
$this->setOptions($options);
if ($input !== null) {
$this->setInput($input);
}
if ($output !== null) {
$this->setOutput($output);
}
}
/**
* @inheritDoc
*/
public function setOptions(array $options): AdapterInterface
{
$this->options = $options;
if (isset($options['default_migration_table'])) {
trigger_error('The default_migration_table setting for adapter has been deprecated since 0.13.0. Use `migration_table` instead.', E_USER_DEPRECATED);
if (!isset($options['migration_table'])) {
$options['migration_table'] = $options['default_migration_table'];
}
}
if (isset($options['migration_table'])) {
$this->setSchemaTableName($options['migration_table']);
}
if (isset($options['data_domain'])) {
$this->setDataDomain($options['data_domain']);
}
return $this;
}
/**
* @inheritDoc
*/
public function getOptions(): array
{
return $this->options;
}
/**
* @inheritDoc
*/
public function hasOption(string $name): bool
{
return isset($this->options[$name]);
}
/**
* @inheritDoc
*/
public function getOption(string $name)
{
if (!$this->hasOption($name)) {
return null;
}
return $this->options[$name];
}
/**
* @inheritDoc
*/
public function setInput(InputInterface $input): AdapterInterface
{
$this->input = $input;
return $this;
}
/**
* @inheritDoc
*/
public function getInput(): ?InputInterface
{
return $this->input;
}
/**
* @inheritDoc
*/
public function setOutput(OutputInterface $output): AdapterInterface
{
$this->output = $output;
return $this;
}
/**
* @inheritDoc
*/
public function getOutput(): OutputInterface
{
if ($this->output === null) {
$output = new NullOutput();
$this->setOutput($output);
}
return $this->output;
}
/**
* @inheritDoc
* @return array<int>
*/
public function getVersions(): array
{
$rows = $this->getVersionLog();
return array_keys($rows);
}
/**
* Gets the schema table name.
*
* @return string
*/
public function getSchemaTableName(): string
{
return $this->schemaTableName;
}
/**
* Sets the schema table name.
*
* @param string $schemaTableName Schema Table Name
* @return $this
*/
public function setSchemaTableName(string $schemaTableName)
{
$this->schemaTableName = $schemaTableName;
return $this;
}
/**
* Gets the data domain.
*
* @return array
*/
public function getDataDomain(): array
{
return $this->dataDomain;
}
/**
* Sets the data domain.
*
* @param array $dataDomain Array for the data domain
* @return $this
*/
public function setDataDomain(array $dataDomain)
{
$this->dataDomain = [];
// Iterate over data domain field definitions and perform initial and
// simple normalization. We make sure the definition as a base 'type'
// and it is compatible with the base Phinx types.
foreach ($dataDomain as $type => $options) {
if (!isset($options['type'])) {
throw new \InvalidArgumentException(sprintf(
'You must specify a type for data domain type "%s".',
$type
));
}
// Replace type if it's the name of a Phinx constant
if (defined('static::' . $options['type'])) {
$options['type'] = constant('static::' . $options['type']);
}
if (!in_array($options['type'], $this->getColumnTypes(), true)) {
throw new \InvalidArgumentException(sprintf(
'An invalid column type "%s" was specified for data domain type "%s".',
$options['type'],
$type
));
}
$internal_type = $options['type'];
unset($options['type']);
// Do a simple replacement for the 'length' / 'limit' option and
// detect hinting values for 'limit'.
if (isset($options['length'])) {
$options['limit'] = $options['length'];
unset($options['length']);
}
if (isset($options['limit']) && !is_numeric($options['limit'])) {
if (!defined('static::' . $options['limit'])) {
throw new \InvalidArgumentException(sprintf(
'An invalid limit value "%s" was specified for data domain type "%s".',
$options['limit'],
$type
));
}
$options['limit'] = constant('static::' . $options['limit']);
}
// Save the data domain types in a more suitable format
$this->dataDomain[$type] = [
'type' => $internal_type,
'options' => $options,
];
}
return $this;
}
/**
* @inheritdoc
*/
public function getColumnForType(string $columnName, string $type, array $options): Column
{
$column = new Column();
$column->setName($columnName);
if (array_key_exists($type, $this->getDataDomain())) {
$column->setType($this->dataDomain[$type]['type']);
$column->setOptions($this->dataDomain[$type]['options']);
} else {
$column->setType($type);
}
$column->setOptions($options);
return $column;
}
/**
* @inheritDoc
* @throws \InvalidArgumentException
* @return void
*/
public function createSchemaTable(): void
{
try {
$options = [
'id' => false,
'primary_key' => 'version',
];
$table = new Table($this->getSchemaTableName(), $options, $this);
$table->addColumn('version', 'biginteger', ['null' => false])
->addColumn('migration_name', 'string', ['limit' => 100, 'default' => null, 'null' => true])
->addColumn('start_time', 'timestamp', ['default' => null, 'null' => true])
->addColumn('end_time', 'timestamp', ['default' => null, 'null' => true])
->addColumn('breakpoint', 'boolean', ['default' => false, 'null' => false])
->save();
} catch (Exception $exception) {
throw new InvalidArgumentException(
'There was a problem creating the schema table: ' . $exception->getMessage(),
(int)$exception->getCode(),
$exception
);
}
}
/**
* @inheritDoc
*/
public function getAdapterType(): string
{
return $this->getOption('adapter');
}
/**
* @inheritDoc
*/
public function isValidColumnType(Column $column): bool
{
return $column->getType() instanceof Literal || in_array($column->getType(), $this->getColumnTypes(), true);
}
/**
* Determines if instead of executing queries a dump to standard output is needed
*
* @return bool
*/
public function isDryRunEnabled(): bool
{
/** @var \think\console\Input|null $input */
$input = $this->getInput();
return $input && $input->hasOption('dry-run') ? (bool)$input->getOption('dry-run') : false;
}
/**
* Adds user-created tables (e.g. not phinxlog) to a cached list
*
* @param string $tableName The name of the table
* @return void
*/
protected function addCreatedTable(string $tableName): void
{
$tableName = $this->quoteTableName($tableName);
if (substr_compare($tableName, 'phinxlog', -strlen('phinxlog')) !== 0) {
$this->createdTables[] = $tableName;
}
}
/**
* Updates the name of the cached table
*
* @param string $tableName Original name of the table
* @param string $newTableName New name of the table
* @return void
*/
protected function updateCreatedTableName(string $tableName, string $newTableName): void
{
$tableName = $this->quoteTableName($tableName);
$newTableName = $this->quoteTableName($newTableName);
$key = array_search($tableName, $this->createdTables, true);
if ($key !== false) {
$this->createdTables[$key] = $newTableName;
}
}
/**
* Removes table from the cached created list
*
* @param string $tableName The name of the table
* @return void
*/
protected function removeCreatedTable(string $tableName): void
{
$tableName = $this->quoteTableName($tableName);
$key = array_search($tableName, $this->createdTables, true);
if ($key !== false) {
unset($this->createdTables[$key]);
}
}
/**
* Check if the table is in the cached list of created tables
*
* @param string $tableName The name of the table
* @return bool
*/
protected function hasCreatedTable(string $tableName): bool
{
$tableName = $this->quoteTableName($tableName);
return in_array($tableName, $this->createdTables, true);
}
}

View File

@@ -0,0 +1,172 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use RuntimeException;
/**
* Adapter factory and registry.
*
* Used for registering adapters and creating instances of adapters.
*
* @author Woody Gilk <woody.gilk@gmail.com>
*/
class AdapterFactory
{
/**
* @var \Phinx\Db\Adapter\AdapterFactory|null
*/
protected static $instance;
/**
* Get the factory singleton instance.
*
* @return \Phinx\Db\Adapter\AdapterFactory
*/
public static function instance()
{
if (!static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Class map of database adapters, indexed by PDO::ATTR_DRIVER_NAME.
*
* @var array<string, \Phinx\Db\Adapter\AdapterInterface|string>
* @phpstan-var array<string, \Phinx\Db\Adapter\AdapterInterface|class-string<\Phinx\Db\Adapter\AdapterInterface>>
*/
protected $adapters = [
'mysql' => 'Phinx\Db\Adapter\MysqlAdapter',
'pgsql' => 'Phinx\Db\Adapter\PostgresAdapter',
'sqlite' => 'Phinx\Db\Adapter\SQLiteAdapter',
'sqlsrv' => 'Phinx\Db\Adapter\SqlServerAdapter',
];
/**
* Class map of adapters wrappers, indexed by name.
*
* @var array<string, \Phinx\Db\Adapter\WrapperInterface|string>
*/
protected $wrappers = [
'prefix' => 'Phinx\Db\Adapter\TablePrefixAdapter',
'proxy' => 'Phinx\Db\Adapter\ProxyAdapter',
'timed' => 'Phinx\Db\Adapter\TimedOutputAdapter',
];
/**
* Register an adapter class with a given name.
*
* @param string $name Name
* @param object|string $class Class
* @throws \RuntimeException
* @return $this
*/
public function registerAdapter(string $name, $class)
{
if (!is_subclass_of($class, 'Phinx\Db\Adapter\AdapterInterface')) {
throw new RuntimeException(sprintf(
'Adapter class "%s" must implement Phinx\\Db\\Adapter\\AdapterInterface',
is_string($class) ? $class : get_class($class)
));
}
$this->adapters[$name] = $class;
return $this;
}
/**
* Get an adapter class by name.
*
* @param string $name Name
* @throws \RuntimeException
* @return object|string
* @phpstan-return object|class-string<\Phinx\Db\Adapter\AdapterInterface>
*/
protected function getClass(string $name)
{
if (empty($this->adapters[$name])) {
throw new RuntimeException(sprintf(
'Adapter "%s" has not been registered',
$name
));
}
return $this->adapters[$name];
}
/**
* Get an adapter instance by name.
*
* @param string $name Name
* @param array<string, mixed> $options Options
* @return \Phinx\Db\Adapter\AdapterInterface
*/
public function getAdapter(string $name, array $options): AdapterInterface
{
$class = $this->getClass($name);
return new $class($options);
}
/**
* Add or replace a wrapper with a fully qualified class name.
*
* @param string $name Name
* @param object|string $class Class
* @throws \RuntimeException
* @return $this
*/
public function registerWrapper(string $name, $class)
{
if (!is_subclass_of($class, 'Phinx\Db\Adapter\WrapperInterface')) {
throw new RuntimeException(sprintf(
'Wrapper class "%s" must be implement Phinx\\Db\\Adapter\\WrapperInterface',
is_string($class) ? $class : get_class($class)
));
}
$this->wrappers[$name] = $class;
return $this;
}
/**
* Get a wrapper class by name.
*
* @param string $name Name
* @throws \RuntimeException
* @return \Phinx\Db\Adapter\WrapperInterface|string
*/
protected function getWrapperClass(string $name)
{
if (empty($this->wrappers[$name])) {
throw new RuntimeException(sprintf(
'Wrapper "%s" has not been registered',
$name
));
}
return $this->wrappers[$name];
}
/**
* Get a wrapper instance by name.
*
* @param string $name Name
* @param \Phinx\Db\Adapter\AdapterInterface $adapter Adapter
* @return \Phinx\Db\Adapter\AdapterWrapper
*/
public function getWrapper(string $name, AdapterInterface $adapter): AdapterWrapper
{
$class = $this->getWrapperClass($name);
return new $class($adapter);
}
}

View File

@@ -0,0 +1,505 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use Cake\Database\Query;
use Phinx\Db\Table\Column;
use Phinx\Db\Table\Table;
use Phinx\Migration\MigrationInterface;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
/**
* Adapter Interface.
*
* @author Rob Morgan <robbym@gmail.com>
* @method \PDO getConnection()
*/
interface AdapterInterface
{
public const PHINX_TYPE_STRING = 'string';
public const PHINX_TYPE_CHAR = 'char';
public const PHINX_TYPE_TEXT = 'text';
public const PHINX_TYPE_INTEGER = 'integer';
public const PHINX_TYPE_TINY_INTEGER = 'tinyinteger';
public const PHINX_TYPE_SMALL_INTEGER = 'smallinteger';
public const PHINX_TYPE_BIG_INTEGER = 'biginteger';
public const PHINX_TYPE_BIT = 'bit';
public const PHINX_TYPE_FLOAT = 'float';
public const PHINX_TYPE_DECIMAL = 'decimal';
public const PHINX_TYPE_DOUBLE = 'double';
public const PHINX_TYPE_DATETIME = 'datetime';
public const PHINX_TYPE_TIMESTAMP = 'timestamp';
public const PHINX_TYPE_TIME = 'time';
public const PHINX_TYPE_DATE = 'date';
public const PHINX_TYPE_BINARY = 'binary';
public const PHINX_TYPE_VARBINARY = 'varbinary';
public const PHINX_TYPE_BINARYUUID = 'binaryuuid';
public const PHINX_TYPE_BLOB = 'blob';
public const PHINX_TYPE_TINYBLOB = 'tinyblob'; // Specific to Mysql.
public const PHINX_TYPE_MEDIUMBLOB = 'mediumblob'; // Specific to Mysql
public const PHINX_TYPE_LONGBLOB = 'longblob'; // Specific to Mysql
public const PHINX_TYPE_BOOLEAN = 'boolean';
public const PHINX_TYPE_JSON = 'json';
public const PHINX_TYPE_JSONB = 'jsonb';
public const PHINX_TYPE_UUID = 'uuid';
public const PHINX_TYPE_FILESTREAM = 'filestream';
// Geospatial database types
public const PHINX_TYPE_GEOMETRY = 'geometry';
public const PHINX_TYPE_GEOGRAPHY = 'geography';
public const PHINX_TYPE_POINT = 'point';
public const PHINX_TYPE_LINESTRING = 'linestring';
public const PHINX_TYPE_POLYGON = 'polygon';
public const PHINX_TYPES_GEOSPATIAL = [
self::PHINX_TYPE_GEOMETRY,
self::PHINX_TYPE_POINT,
self::PHINX_TYPE_LINESTRING,
self::PHINX_TYPE_POLYGON,
];
// only for mysql so far
public const PHINX_TYPE_MEDIUM_INTEGER = 'mediuminteger';
public const PHINX_TYPE_ENUM = 'enum';
public const PHINX_TYPE_SET = 'set';
public const PHINX_TYPE_YEAR = 'year';
// only for postgresql so far
public const PHINX_TYPE_CIDR = 'cidr';
public const PHINX_TYPE_INET = 'inet';
public const PHINX_TYPE_MACADDR = 'macaddr';
public const PHINX_TYPE_INTERVAL = 'interval';
/**
* Get all migrated version numbers.
*
* @return array<int>
*/
public function getVersions(): array;
/**
* Get all migration log entries, indexed by version creation time and sorted ascendingly by the configuration's
* version order option
*
* @return array<int, mixed>
*/
public function getVersionLog(): array;
/**
* Set adapter configuration options.
*
* @param array<string, mixed> $options Options
* @return $this
*/
public function setOptions(array $options);
/**
* Get all adapter options.
*
* @return array<string, mixed>
*/
public function getOptions(): array;
/**
* Check if an option has been set.
*
* @param string $name Name
* @return bool
*/
public function hasOption(string $name): bool;
/**
* Get a single adapter option, or null if the option does not exist.
*
* @param string $name Name
* @return mixed
*/
public function getOption(string $name);
/**
* Sets the console input.
*
* @param \think\console\Input $input Input
* @return $this
*/
public function setInput(InputInterface $input);
/**
* Gets the console input.
*
* @return \think\console\Input|null
*/
public function getInput(): ?InputInterface;
/**
* Sets the console output.
*
* @param \think\console\Output $output Output
* @return $this
*/
public function setOutput(OutputInterface $output);
/**
* Gets the console output.
*
* @return \think\console\Output
*/
public function getOutput(): OutputInterface;
/**
* Returns a new Phinx\Db\Table\Column using the existent data domain.
*
* @param string $columnName The desired column name
* @param string $type The type for the column. Can be a data domain type.
* @param array<string, mixed> $options Options array
* @return \Phinx\Db\Table\Column
*/
public function getColumnForType(string $columnName, string $type, array $options): Column;
/**
* Records a migration being run.
*
* @param \Phinx\Migration\MigrationInterface $migration Migration
* @param string $direction Direction
* @param string $startTime Start Time
* @param string $endTime End Time
* @return $this
*/
public function migrated(MigrationInterface $migration, string $direction, string $startTime, string $endTime);
/**
* Toggle a migration breakpoint.
*
* @param \Phinx\Migration\MigrationInterface $migration Migration
* @return $this
*/
public function toggleBreakpoint(MigrationInterface $migration);
/**
* Reset all migration breakpoints.
*
* @return int The number of breakpoints reset
*/
public function resetAllBreakpoints(): int;
/**
* Set a migration breakpoint.
*
* @param \Phinx\Migration\MigrationInterface $migration The migration target for the breakpoint set
* @return $this
*/
public function setBreakpoint(MigrationInterface $migration);
/**
* Unset a migration breakpoint.
*
* @param \Phinx\Migration\MigrationInterface $migration The migration target for the breakpoint unset
* @return $this
*/
public function unsetBreakpoint(MigrationInterface $migration);
/**
* Creates the schema table.
*
* @return void
*/
public function createSchemaTable(): void;
/**
* Returns the adapter type.
*
* @return string
*/
public function getAdapterType(): string;
/**
* Initializes the database connection.
*
* @throws \RuntimeException When the requested database driver is not installed.
* @return void
*/
public function connect(): void;
/**
* Closes the database connection.
*
* @return void
*/
public function disconnect(): void;
/**
* Does the adapter support transactions?
*
* @return bool
*/
public function hasTransactions(): bool;
/**
* Begin a transaction.
*
* @return void
*/
public function beginTransaction(): void;
/**
* Commit a transaction.
*
* @return void
*/
public function commitTransaction(): void;
/**
* Rollback a transaction.
*
* @return void
*/
public function rollbackTransaction(): void;
/**
* Executes a SQL statement and returns the number of affected rows.
*
* @param string $sql SQL
* @param array $params parameters to use for prepared query
* @return int
*/
public function execute(string $sql, array $params = []): int;
/**
* Executes a list of migration actions for the given table
*
* @param \Phinx\Db\Table\Table $table The table to execute the actions for
* @param \Phinx\Db\Action\Action[] $actions The table to execute the actions for
* @return void
*/
public function executeActions(Table $table, array $actions): void;
/**
* Returns a new Query object
*
* @return \Cake\Database\Query
*/
public function getQueryBuilder(): Query;
/**
* Executes a SQL statement.
*
* The return type depends on the underlying adapter being used.
*
* @param string $sql SQL
* @param array $params parameters to use for prepared query
* @return mixed
*/
public function query(string $sql, array $params = []);
/**
* Executes a query and returns only one row as an array.
*
* @param string $sql SQL
* @return array|false
*/
public function fetchRow(string $sql);
/**
* Executes a query and returns an array of rows.
*
* @param string $sql SQL
* @return array
*/
public function fetchAll(string $sql): array;
/**
* Inserts data into a table.
*
* @param \Phinx\Db\Table\Table $table Table where to insert data
* @param array $row Row
* @return void
*/
public function insert(Table $table, array $row): void;
/**
* Inserts data into a table in a bulk.
*
* @param \Phinx\Db\Table\Table $table Table where to insert data
* @param array $rows Rows
* @return void
*/
public function bulkinsert(Table $table, array $rows): void;
/**
* Quotes a table name for use in a query.
*
* @param string $tableName Table name
* @return string
*/
public function quoteTableName(string $tableName): string;
/**
* Quotes a column name for use in a query.
*
* @param string $columnName Table name
* @return string
*/
public function quoteColumnName(string $columnName): string;
/**
* Checks to see if a table exists.
*
* @param string $tableName Table name
* @return bool
*/
public function hasTable(string $tableName): bool;
/**
* Creates the specified database table.
*
* @param \Phinx\Db\Table\Table $table Table
* @param \Phinx\Db\Table\Column[] $columns List of columns in the table
* @param \Phinx\Db\Table\Index[] $indexes List of indexes for the table
* @return void
*/
public function createTable(Table $table, array $columns = [], array $indexes = []): void;
/**
* Truncates the specified table
*
* @param string $tableName Table name
* @return void
*/
public function truncateTable(string $tableName): void;
/**
* Returns table columns
*
* @param string $tableName Table name
* @return \Phinx\Db\Table\Column[]
*/
public function getColumns(string $tableName): array;
/**
* Checks to see if a column exists.
*
* @param string $tableName Table name
* @param string $columnName Column name
* @return bool
*/
public function hasColumn(string $tableName, string $columnName): bool;
/**
* Checks to see if an index exists.
*
* @param string $tableName Table name
* @param string|string[] $columns Column(s)
* @return bool
*/
public function hasIndex(string $tableName, $columns): bool;
/**
* Checks to see if an index specified by name exists.
*
* @param string $tableName Table name
* @param string $indexName Index name
* @return bool
*/
public function hasIndexByName(string $tableName, string $indexName): bool;
/**
* Checks to see if the specified primary key exists.
*
* @param string $tableName Table name
* @param string|string[] $columns Column(s)
* @param string|null $constraint Constraint name
* @return bool
*/
public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = null): bool;
/**
* Checks to see if a foreign key exists.
*
* @param string $tableName Table name
* @param string|string[] $columns Column(s)
* @param string|null $constraint Constraint name
* @return bool
*/
public function hasForeignKey(string $tableName, $columns, ?string $constraint = null): bool;
/**
* Returns an array of the supported Phinx column types.
*
* @return string[]
*/
public function getColumnTypes(): array;
/**
* Checks that the given column is of a supported type.
*
* @param \Phinx\Db\Table\Column $column Column
* @return bool
*/
public function isValidColumnType(Column $column): bool;
/**
* Converts the Phinx logical type to the adapter's SQL type.
*
* @param \Phinx\Util\Literal|string $type Type
* @param int|null $limit Limit
* @return array
*/
public function getSqlType($type, ?int $limit = null): array;
/**
* Creates a new database.
*
* @param string $name Database Name
* @param array<string, mixed> $options Options
* @return void
*/
public function createDatabase(string $name, array $options = []): void;
/**
* Checks to see if a database exists.
*
* @param string $name Database Name
* @return bool
*/
public function hasDatabase(string $name): bool;
/**
* Drops the specified database.
*
* @param string $name Database Name
* @return void
*/
public function dropDatabase(string $name): void;
/**
* Creates the specified schema or throws an exception
* if there is no support for it.
*
* @param string $schemaName Schema Name
* @return void
*/
public function createSchema(string $schemaName = 'public'): void;
/**
* Drops the specified schema table or throws an exception
* if there is no support for it.
*
* @param string $schemaName Schema name
* @return void
*/
public function dropSchema(string $schemaName): void;
/**
* Cast a value to a boolean appropriate for the adapter.
*
* @param mixed $value The value to be cast
* @return mixed
*/
public function castToBool($value);
}

View File

@@ -0,0 +1,487 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use Cake\Database\Query;
use Phinx\Db\Table\Column;
use Phinx\Db\Table\Table;
use Phinx\Migration\MigrationInterface;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
/**
* Adapter Wrapper.
*
* Proxy commands through to another adapter, allowing modification of
* parameters during calls.
*
* @author Woody Gilk <woody.gilk@gmail.com>
*/
abstract class AdapterWrapper implements AdapterInterface, WrapperInterface
{
/**
* @var \Phinx\Db\Adapter\AdapterInterface
*/
protected $adapter;
/**
* @inheritDoc
*/
public function __construct(AdapterInterface $adapter)
{
$this->setAdapter($adapter);
}
/**
* @inheritDoc
*/
public function setAdapter(AdapterInterface $adapter): AdapterInterface
{
$this->adapter = $adapter;
return $this;
}
/**
* @inheritDoc
*/
public function getAdapter(): AdapterInterface
{
return $this->adapter;
}
/**
* @inheritDoc
*/
public function setOptions(array $options): AdapterInterface
{
$this->adapter->setOptions($options);
return $this;
}
/**
* @inheritDoc
*/
public function getOptions(): array
{
return $this->adapter->getOptions();
}
/**
* @inheritDoc
*/
public function hasOption(string $name): bool
{
return $this->adapter->hasOption($name);
}
/**
* @inheritDoc
*/
public function getOption(string $name)
{
return $this->adapter->getOption($name);
}
/**
* @inheritDoc
*/
public function setInput(InputInterface $input): AdapterInterface
{
$this->adapter->setInput($input);
return $this;
}
/**
* @inheritDoc
*/
public function getInput(): InputInterface
{
return $this->adapter->getInput();
}
/**
* @inheritDoc
*/
public function setOutput(OutputInterface $output): AdapterInterface
{
$this->adapter->setOutput($output);
return $this;
}
/**
* @inheritDoc
*/
public function getOutput(): OutputInterface
{
return $this->adapter->getOutput();
}
/**
* @inheritDoc
*/
public function getColumnForType(string $columnName, string $type, array $options): Column
{
return $this->adapter->getColumnForType($columnName, $type, $options);
}
/**
* @inheritDoc
*/
public function connect(): void
{
$this->getAdapter()->connect();
}
/**
* @inheritDoc
*/
public function disconnect(): void
{
$this->getAdapter()->disconnect();
}
/**
* @inheritDoc
*/
public function execute(string $sql, array $params = []): int
{
return $this->getAdapter()->execute($sql, $params);
}
/**
* @inheritDoc
*/
public function query(string $sql, array $params = [])
{
return $this->getAdapter()->query($sql, $params);
}
/**
* @inheritDoc
*/
public function insert(Table $table, array $row): void
{
$this->getAdapter()->insert($table, $row);
}
/**
* @inheritDoc
*/
public function bulkinsert(Table $table, array $rows): void
{
$this->getAdapter()->bulkinsert($table, $rows);
}
/**
* @inheritDoc
*/
public function fetchRow(string $sql)
{
return $this->getAdapter()->fetchRow($sql);
}
/**
* @inheritDoc
*/
public function fetchAll(string $sql): array
{
return $this->getAdapter()->fetchAll($sql);
}
/**
* @inheritDoc
*/
public function getVersions(): array
{
return $this->getAdapter()->getVersions();
}
/**
* @inheritDoc
*/
public function getVersionLog(): array
{
return $this->getAdapter()->getVersionLog();
}
/**
* @inheritDoc
*/
public function migrated(MigrationInterface $migration, string $direction, string $startTime, string $endTime): AdapterInterface
{
$this->getAdapter()->migrated($migration, $direction, $startTime, $endTime);
return $this;
}
/**
* @inheritDoc
*/
public function toggleBreakpoint(MigrationInterface $migration): AdapterInterface
{
$this->getAdapter()->toggleBreakpoint($migration);
return $this;
}
/**
* @inheritDoc
*/
public function resetAllBreakpoints(): int
{
return $this->getAdapter()->resetAllBreakpoints();
}
/**
* @inheritDoc
*/
public function setBreakpoint(MigrationInterface $migration): AdapterInterface
{
$this->getAdapter()->setBreakpoint($migration);
return $this;
}
/**
* @inheritDoc
*/
public function unsetBreakpoint(MigrationInterface $migration): AdapterInterface
{
$this->getAdapter()->unsetBreakpoint($migration);
return $this;
}
/**
* @inheritDoc
*/
public function createSchemaTable(): void
{
$this->getAdapter()->createSchemaTable();
}
/**
* @inheritDoc
*/
public function getColumnTypes(): array
{
return $this->getAdapter()->getColumnTypes();
}
/**
* @inheritDoc
*/
public function isValidColumnType(Column $column): bool
{
return $this->getAdapter()->isValidColumnType($column);
}
/**
* @inheritDoc
*/
public function hasTransactions(): bool
{
return $this->getAdapter()->hasTransactions();
}
/**
* @inheritDoc
*/
public function beginTransaction(): void
{
$this->getAdapter()->beginTransaction();
}
/**
* @inheritDoc
*/
public function commitTransaction(): void
{
$this->getAdapter()->commitTransaction();
}
/**
* @inheritDoc
*/
public function rollbackTransaction(): void
{
$this->getAdapter()->rollbackTransaction();
}
/**
* @inheritDoc
*/
public function quoteTableName(string $tableName): string
{
return $this->getAdapter()->quoteTableName($tableName);
}
/**
* @inheritDoc
*/
public function quoteColumnName(string $columnName): string
{
return $this->getAdapter()->quoteColumnName($columnName);
}
/**
* @inheritDoc
*/
public function hasTable(string $tableName): bool
{
return $this->getAdapter()->hasTable($tableName);
}
/**
* @inheritDoc
*/
public function createTable(Table $table, array $columns = [], array $indexes = []): void
{
$this->getAdapter()->createTable($table, $columns, $indexes);
}
/**
* @inheritDoc
*/
public function getColumns(string $tableName): array
{
return $this->getAdapter()->getColumns($tableName);
}
/**
* @inheritDoc
*/
public function hasColumn(string $tableName, string $columnName): bool
{
return $this->getAdapter()->hasColumn($tableName, $columnName);
}
/**
* @inheritDoc
*/
public function hasIndex(string $tableName, $columns): bool
{
return $this->getAdapter()->hasIndex($tableName, $columns);
}
/**
* @inheritDoc
*/
public function hasIndexByName(string $tableName, string $indexName): bool
{
return $this->getAdapter()->hasIndexByName($tableName, $indexName);
}
/**
* @inheritDoc
*/
public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = null): bool
{
return $this->getAdapter()->hasPrimaryKey($tableName, $columns, $constraint);
}
/**
* @inheritDoc
*/
public function hasForeignKey(string $tableName, $columns, ?string $constraint = null): bool
{
return $this->getAdapter()->hasForeignKey($tableName, $columns, $constraint);
}
/**
* @inheritDoc
*/
public function getSqlType($type, ?int $limit = null): array
{
return $this->getAdapter()->getSqlType($type, $limit);
}
/**
* @inheritDoc
*/
public function createDatabase(string $name, array $options = []): void
{
$this->getAdapter()->createDatabase($name, $options);
}
/**
* @inheritDoc
*/
public function hasDatabase(string $name): bool
{
return $this->getAdapter()->hasDatabase($name);
}
/**
* @inheritDoc
*/
public function dropDatabase(string $name): void
{
$this->getAdapter()->dropDatabase($name);
}
/**
* @inheritDoc
*/
public function createSchema(string $schemaName = 'public'): void
{
$this->getAdapter()->createSchema($schemaName);
}
/**
* @inheritDoc
*/
public function dropSchema(string $schemaName): void
{
$this->getAdapter()->dropSchema($schemaName);
}
/**
* @inheritDoc
*/
public function truncateTable(string $tableName): void
{
$this->getAdapter()->truncateTable($tableName);
}
/**
* @inheritDoc
*/
public function castToBool($value)
{
return $this->getAdapter()->castToBool($value);
}
/**
* @return \PDO
*/
public function getConnection()
{
return $this->getAdapter()->getConnection();
}
/**
* @inheritDoc
*/
public function executeActions(Table $table, array $actions): void
{
$this->getAdapter()->executeActions($table, $actions);
}
/**
* @inheritDoc
*/
public function getQueryBuilder(): Query
{
return $this->getAdapter()->getQueryBuilder();
}
}

View File

@@ -0,0 +1,139 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use Phinx\Db\Table\Column;
use Phinx\Db\Table\ForeignKey;
use Phinx\Db\Table\Index;
use Phinx\Db\Table\Table;
/**
* Represents an adapter that is capable of directly executing alter
* instructions, without having to plan them first.
*/
interface DirectActionInterface
{
/**
* Renames the specified database table.
*
* @param string $tableName Table name
* @param string $newName New Name
* @return void
*/
public function renameTable(string $tableName, string $newName): void;
/**
* Drops the specified database table.
*
* @param string $tableName Table name
* @return void
*/
public function dropTable(string $tableName): void;
/**
* Changes the primary key of the specified database table.
*
* @param \Phinx\Db\Table\Table $table Table
* @param string|string[]|null $newColumns Column name(s) to belong to the primary key, or null to drop the key
* @return void
*/
public function changePrimaryKey(Table $table, $newColumns): void;
/**
* Changes the comment of the specified database table.
*
* @param \Phinx\Db\Table\Table $table Table
* @param string|null $newComment New comment string, or null to drop the comment
* @return void
*/
public function changeComment(Table $table, ?string $newComment): void;
/**
* Adds the specified column to a database table.
*
* @param \Phinx\Db\Table\Table $table Table
* @param \Phinx\Db\Table\Column $column Column
* @return void
*/
public function addColumn(Table $table, Column $column): void;
/**
* Renames the specified column.
*
* @param string $tableName Table name
* @param string $columnName Column Name
* @param string $newColumnName New Column Name
* @return void
*/
public function renameColumn(string $tableName, string $columnName, string $newColumnName): void;
/**
* Change a table column type.
*
* @param string $tableName Table name
* @param string $columnName Column Name
* @param \Phinx\Db\Table\Column $newColumn New Column
* @return void
*/
public function changeColumn(string $tableName, string $columnName, Column $newColumn): void;
/**
* Drops the specified column.
*
* @param string $tableName Table name
* @param string $columnName Column Name
* @return void
*/
public function dropColumn(string $tableName, string $columnName): void;
/**
* Adds the specified index to a database table.
*
* @param \Phinx\Db\Table\Table $table Table
* @param \Phinx\Db\Table\Index $index Index
* @return void
*/
public function addIndex(Table $table, Index $index): void;
/**
* Drops the specified index from a database table.
*
* @param string $tableName the name of the table
* @param string|string[] $columns Column(s)
* @return void
*/
public function dropIndex(string $tableName, $columns): void;
/**
* Drops the index specified by name from a database table.
*
* @param string $tableName The table name where the index is
* @param string $indexName The name of the index
* @return void
*/
public function dropIndexByName(string $tableName, string $indexName): void;
/**
* Adds the specified foreign key to a database table.
*
* @param \Phinx\Db\Table\Table $table The table to add the foreign key to
* @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add
* @return void
*/
public function addForeignKey(Table $table, ForeignKey $foreignKey): void;
/**
* Drops the specified foreign key from a database table.
*
* @param string $tableName The table to drop the foreign key from
* @param string[] $columns Column(s)
* @param string|null $constraint Constraint name
* @return void
*/
public function dropForeignKey(string $tableName, array $columns, ?string $constraint = null): void;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use Phinx\Db\Action\AddColumn;
use Phinx\Db\Action\AddForeignKey;
use Phinx\Db\Action\AddIndex;
use Phinx\Db\Action\CreateTable;
use Phinx\Db\Action\DropForeignKey;
use Phinx\Db\Action\DropIndex;
use Phinx\Db\Action\DropTable;
use Phinx\Db\Action\RemoveColumn;
use Phinx\Db\Action\RenameColumn;
use Phinx\Db\Action\RenameTable;
use Phinx\Db\Plan\Intent;
use Phinx\Db\Plan\Plan;
use Phinx\Db\Table\Table;
use Phinx\Migration\IrreversibleMigrationException;
/**
* Phinx Proxy Adapter.
*
* Used for recording migration commands to automatically reverse them.
*
* @author Rob Morgan <robbym@gmail.com>
*/
class ProxyAdapter extends AdapterWrapper
{
/**
* @var \Phinx\Db\Action\Action[]
*/
protected $commands = [];
/**
* @inheritDoc
*/
public function getAdapterType(): string
{
return 'ProxyAdapter';
}
/**
* @inheritDoc
*/
public function createTable(Table $table, array $columns = [], array $indexes = []): void
{
$this->commands[] = new CreateTable($table);
}
/**
* @inheritDoc
*/
public function executeActions(Table $table, array $actions): void
{
$this->commands = array_merge($this->commands, $actions);
}
/**
* Gets an array of the recorded commands in reverse.
*
* @throws \Phinx\Migration\IrreversibleMigrationException if a command cannot be reversed.
* @return \Phinx\Db\Plan\Intent
*/
public function getInvertedCommands(): Intent
{
$inverted = new Intent();
foreach (array_reverse($this->commands) as $command) {
switch (true) {
case $command instanceof CreateTable:
/** @var \Phinx\Db\Action\CreateTable $command */
$inverted->addAction(new DropTable($command->getTable()));
break;
case $command instanceof RenameTable:
/** @var \Phinx\Db\Action\RenameTable $command */
$inverted->addAction(new RenameTable(new Table($command->getNewName()), $command->getTable()->getName()));
break;
case $command instanceof AddColumn:
/** @var \Phinx\Db\Action\AddColumn $command */
$inverted->addAction(new RemoveColumn($command->getTable(), $command->getColumn()));
break;
case $command instanceof RenameColumn:
/** @var \Phinx\Db\Action\RenameColumn $command */
$column = clone $command->getColumn();
$name = $column->getName();
$column->setName($command->getNewName());
$inverted->addAction(new RenameColumn($command->getTable(), $column, $name));
break;
case $command instanceof AddIndex:
/** @var \Phinx\Db\Action\AddIndex $command */
$inverted->addAction(new DropIndex($command->getTable(), $command->getIndex()));
break;
case $command instanceof AddForeignKey:
/** @var \Phinx\Db\Action\AddForeignKey $command */
$inverted->addAction(new DropForeignKey($command->getTable(), $command->getForeignKey()));
break;
default:
throw new IrreversibleMigrationException(sprintf(
'Cannot reverse a "%s" command',
get_class($command)
));
}
}
return $inverted;
}
/**
* Execute the recorded commands in reverse.
*
* @return void
*/
public function executeInvertedCommands(): void
{
$plan = new Plan($this->getInvertedCommands());
$plan->executeInverse($this->getAdapter());
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,494 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use BadMethodCallException;
use InvalidArgumentException;
use Phinx\Db\Action\AddColumn;
use Phinx\Db\Action\AddForeignKey;
use Phinx\Db\Action\AddIndex;
use Phinx\Db\Action\ChangeColumn;
use Phinx\Db\Action\ChangeComment;
use Phinx\Db\Action\ChangePrimaryKey;
use Phinx\Db\Action\DropForeignKey;
use Phinx\Db\Action\DropIndex;
use Phinx\Db\Action\DropTable;
use Phinx\Db\Action\RemoveColumn;
use Phinx\Db\Action\RenameColumn;
use Phinx\Db\Action\RenameTable;
use Phinx\Db\Table\Column;
use Phinx\Db\Table\ForeignKey;
use Phinx\Db\Table\Index;
use Phinx\Db\Table\Table;
/**
* Table prefix/suffix adapter.
*
* Used for inserting a prefix or suffix into table names.
*
* @author Samuel Fisher <sam@sfisher.co>
*/
class TablePrefixAdapter extends AdapterWrapper implements DirectActionInterface
{
/**
* @inheritDoc
*/
public function getAdapterType(): string
{
return 'TablePrefixAdapter';
}
/**
* @inheritDoc
*/
public function hasTable(string $tableName): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasTable($adapterTableName);
}
/**
* @inheritDoc
*/
public function createTable(Table $table, array $columns = [], array $indexes = []): void
{
$adapterTable = new Table(
$this->getAdapterTableName($table->getName()),
$table->getOptions()
);
parent::createTable($adapterTable, $columns, $indexes);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changePrimaryKey(Table $table, $newColumns): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTable = new Table(
$this->getAdapterTableName($table->getName()),
$table->getOptions()
);
$adapter->changePrimaryKey($adapterTable, $newColumns);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changeComment(Table $table, ?string $newComment): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTable = new Table(
$this->getAdapterTableName($table->getName()),
$table->getOptions()
);
$adapter->changeComment($adapterTable, $newComment);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function renameTable(string $tableName, string $newTableName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapterNewTableName = $this->getAdapterTableName($newTableName);
$adapter->renameTable($adapterTableName, $adapterNewTableName);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropTable(string $tableName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->dropTable($adapterTableName);
}
/**
* @inheritDoc
*/
public function truncateTable(string $tableName): void
{
$adapterTableName = $this->getAdapterTableName($tableName);
parent::truncateTable($adapterTableName);
}
/**
* @inheritDoc
*/
public function getColumns(string $tableName): array
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::getColumns($adapterTableName);
}
/**
* @inheritDoc
*/
public function hasColumn(string $tableName, string $columnName): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasColumn($adapterTableName, $columnName);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addColumn(Table $table, Column $column): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($table->getName());
$adapterTable = new Table($adapterTableName, $table->getOptions());
$adapter->addColumn($adapterTable, $column);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function renameColumn(string $tableName, string $columnName, string $newColumnName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->renameColumn($adapterTableName, $columnName, $newColumnName);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changeColumn(string $tableName, string $columnName, Column $newColumn): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->changeColumn($adapterTableName, $columnName, $newColumn);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropColumn(string $tableName, string $columnName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->dropColumn($adapterTableName, $columnName);
}
/**
* @inheritDoc
*/
public function hasIndex(string $tableName, $columns): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasIndex($adapterTableName, $columns);
}
/**
* @inheritDoc
*/
public function hasIndexByName(string $tableName, string $indexName): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasIndexByName($adapterTableName, $indexName);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addIndex(Table $table, Index $index): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTable = new Table($table->getName(), $table->getOptions());
$adapter->addIndex($adapterTable, $index);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropIndex(string $tableName, $columns): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->dropIndex($adapterTableName, $columns);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropIndexByName(string $tableName, string $indexName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->dropIndexByName($adapterTableName, $indexName);
}
/**
* @inheritDoc
*/
public function hasPrimaryKey(string $tableName, $columns, ?string $constraint = null): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasPrimaryKey($adapterTableName, $columns, $constraint);
}
/**
* @inheritDoc
*/
public function hasForeignKey(string $tableName, $columns, ?string $constraint = null): bool
{
$adapterTableName = $this->getAdapterTableName($tableName);
return parent::hasForeignKey($adapterTableName, $columns, $constraint);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addForeignKey(Table $table, ForeignKey $foreignKey): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($table->getName());
$adapterTable = new Table($adapterTableName, $table->getOptions());
$adapter->addForeignKey($adapterTable, $foreignKey);
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropForeignKey(string $tableName, array $columns, ?string $constraint = null): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The underlying adapter does not implement DirectActionInterface');
}
$adapterTableName = $this->getAdapterTableName($tableName);
$adapter->dropForeignKey($adapterTableName, $columns, $constraint);
}
/**
* @inheritDoc
*/
public function insert(Table $table, array $row): void
{
$adapterTableName = $this->getAdapterTableName($table->getName());
$adapterTable = new Table($adapterTableName, $table->getOptions());
parent::insert($adapterTable, $row);
}
/**
* @inheritDoc
*/
public function bulkinsert(Table $table, array $rows): void
{
$adapterTableName = $this->getAdapterTableName($table->getName());
$adapterTable = new Table($adapterTableName, $table->getOptions());
parent::bulkinsert($adapterTable, $rows);
}
/**
* Gets the table prefix.
*
* @return string
*/
public function getPrefix(): string
{
return (string)$this->getOption('table_prefix');
}
/**
* Gets the table suffix.
*
* @return string
*/
public function getSuffix(): string
{
return (string)$this->getOption('table_suffix');
}
/**
* Applies the prefix and suffix to the table name.
*
* @param string $tableName Table name
* @return string
*/
public function getAdapterTableName(string $tableName): string
{
return $this->getPrefix() . $tableName . $this->getSuffix();
}
/**
* {@inheritDoc}
*
* @throws \InvalidArgumentException
* @return void
*/
public function executeActions(Table $table, array $actions): void
{
$adapterTableName = $this->getAdapterTableName($table->getName());
$adapterTable = new Table($adapterTableName, $table->getOptions());
foreach ($actions as $k => $action) {
switch (true) {
case $action instanceof AddColumn:
/** @var \Phinx\Db\Action\AddColumn $action */
$actions[$k] = new AddColumn($adapterTable, $action->getColumn());
break;
case $action instanceof AddIndex:
/** @var \Phinx\Db\Action\AddIndex $action */
$actions[$k] = new AddIndex($adapterTable, $action->getIndex());
break;
case $action instanceof AddForeignKey:
/** @var \Phinx\Db\Action\AddForeignKey $action */
$foreignKey = clone $action->getForeignKey();
$refTable = $foreignKey->getReferencedTable();
$refTableName = $this->getAdapterTableName($refTable->getName());
$foreignKey->setReferencedTable(new Table($refTableName, $refTable->getOptions()));
$actions[$k] = new AddForeignKey($adapterTable, $foreignKey);
break;
case $action instanceof ChangeColumn:
/** @var \Phinx\Db\Action\ChangeColumn $action */
$actions[$k] = new ChangeColumn($adapterTable, $action->getColumnName(), $action->getColumn());
break;
case $action instanceof DropForeignKey:
/** @var \Phinx\Db\Action\DropForeignKey $action */
$actions[$k] = new DropForeignKey($adapterTable, $action->getForeignKey());
break;
case $action instanceof DropIndex:
/** @var \Phinx\Db\Action\DropIndex $action */
$actions[$k] = new DropIndex($adapterTable, $action->getIndex());
break;
case $action instanceof DropTable:
/** @var \Phinx\Db\Action\DropTable $action */
$actions[$k] = new DropTable($adapterTable);
break;
case $action instanceof RemoveColumn:
/** @var \Phinx\Db\Action\RemoveColumn $action */
$actions[$k] = new RemoveColumn($adapterTable, $action->getColumn());
break;
case $action instanceof RenameColumn:
/** @var \Phinx\Db\Action\RenameColumn $action */
$actions[$k] = new RenameColumn($adapterTable, $action->getColumn(), $action->getNewName());
break;
case $action instanceof RenameTable:
/** @var \Phinx\Db\Action\RenameTable $action */
$actions[$k] = new RenameTable($adapterTable, $this->getAdapterTableName($action->getNewName()));
break;
case $action instanceof ChangePrimaryKey:
/** @var \Phinx\Db\Action\ChangePrimaryKey $action */
$actions[$k] = new ChangePrimaryKey($adapterTable, $action->getNewColumns());
break;
case $action instanceof ChangeComment:
/** @var \Phinx\Db\Action\ChangeComment $action */
$actions[$k] = new ChangeComment($adapterTable, $action->getNewComment());
break;
default:
throw new InvalidArgumentException(
sprintf("Forgot to implement table prefixing for action: '%s'", get_class($action))
);
}
}
parent::executeActions($adapterTable, $actions);
}
}

View File

@@ -0,0 +1,423 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use BadMethodCallException;
use Phinx\Db\Table\Column;
use Phinx\Db\Table\ForeignKey;
use Phinx\Db\Table\Index;
use Phinx\Db\Table\Table;
use think\console\Output as OutputInterface;
/**
* Wraps any adapter to record the time spend executing its commands
*/
class TimedOutputAdapter extends AdapterWrapper implements DirectActionInterface
{
/**
* @inheritDoc
*/
public function getAdapterType(): string
{
return $this->getAdapter()->getAdapterType();
}
/**
* Start timing a command.
*
* @return callable A function that is to be called when the command finishes
*/
public function startCommandTimer(): callable
{
$started = microtime(true);
return function () use ($started) {
$end = microtime(true);
if (OutputInterface::VERBOSITY_VERBOSE <= $this->getOutput()->getVerbosity()) {
$this->getOutput()->writeln(' -> ' . sprintf('%.4fs', $end - $started));
}
};
}
/**
* Write a Phinx command to the output.
*
* @param string $command Command Name
* @param array $args Command Args
* @return void
*/
public function writeCommand(string $command, array $args = []): void
{
if (OutputInterface::VERBOSITY_VERBOSE > $this->getOutput()->getVerbosity()) {
return;
}
if (count($args)) {
$outArr = [];
foreach ($args as $arg) {
if (is_array($arg)) {
$arg = array_map(
function ($value) {
return '\'' . $value . '\'';
},
$arg
);
$outArr[] = '[' . implode(', ', $arg) . ']';
continue;
}
$outArr[] = '\'' . $arg . '\'';
}
$this->getOutput()->writeln(' -- ' . $command . '(' . implode(', ', $outArr) . ')');
return;
}
$this->getOutput()->writeln(' -- ' . $command);
}
/**
* @inheritDoc
*/
public function insert(Table $table, array $row): void
{
$end = $this->startCommandTimer();
$this->writeCommand('insert', [$table->getName()]);
parent::insert($table, $row);
$end();
}
/**
* @inheritDoc
*/
public function bulkinsert(Table $table, array $rows): void
{
$end = $this->startCommandTimer();
$this->writeCommand('bulkinsert', [$table->getName()]);
parent::bulkinsert($table, $rows);
$end();
}
/**
* @inheritDoc
*/
public function createTable(Table $table, array $columns = [], array $indexes = []): void
{
$end = $this->startCommandTimer();
$this->writeCommand('createTable', [$table->getName()]);
parent::createTable($table, $columns, $indexes);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changePrimaryKey(Table $table, $newColumns): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('changePrimaryKey', [$table->getName()]);
$adapter->changePrimaryKey($table, $newColumns);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changeComment(Table $table, ?string $newComment): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('changeComment', [$table->getName()]);
$adapter->changeComment($table, $newComment);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function renameTable(string $tableName, string $newTableName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('renameTable', [$tableName, $newTableName]);
$adapter->renameTable($tableName, $newTableName);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropTable(string $tableName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('dropTable', [$tableName]);
$adapter->dropTable($tableName);
$end();
}
/**
* @inheritDoc
*/
public function truncateTable(string $tableName): void
{
$end = $this->startCommandTimer();
$this->writeCommand('truncateTable', [$tableName]);
parent::truncateTable($tableName);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addColumn(Table $table, Column $column): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand(
'addColumn',
[
$table->getName(),
$column->getName(),
$column->getType(),
]
);
$adapter->addColumn($table, $column);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function renameColumn(string $tableName, string $columnName, string $newColumnName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('renameColumn', [$tableName, $columnName, $newColumnName]);
$adapter->renameColumn($tableName, $columnName, $newColumnName);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function changeColumn(string $tableName, string $columnName, Column $newColumn): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('changeColumn', [$tableName, $columnName, $newColumn->getType()]);
$adapter->changeColumn($tableName, $columnName, $newColumn);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropColumn(string $tableName, string $columnName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('dropColumn', [$tableName, $columnName]);
$adapter->dropColumn($tableName, $columnName);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addIndex(Table $table, Index $index): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('addIndex', [$table->getName(), $index->getColumns()]);
$adapter->addIndex($table, $index);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropIndex(string $tableName, $columns): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('dropIndex', [$tableName, $columns]);
$adapter->dropIndex($tableName, $columns);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropIndexByName(string $tableName, string $indexName): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('dropIndexByName', [$tableName, $indexName]);
$adapter->dropIndexByName($tableName, $indexName);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function addForeignKey(Table $table, ForeignKey $foreignKey): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('addForeignKey', [$table->getName(), $foreignKey->getColumns()]);
$adapter->addForeignKey($table, $foreignKey);
$end();
}
/**
* {@inheritDoc}
*
* @throws \BadMethodCallException
* @return void
*/
public function dropForeignKey(string $tableName, array $columns, ?string $constraint = null): void
{
$adapter = $this->getAdapter();
if (!$adapter instanceof DirectActionInterface) {
throw new BadMethodCallException('The adapter needs to implement DirectActionInterface');
}
$end = $this->startCommandTimer();
$this->writeCommand('dropForeignKey', [$tableName, $columns]);
$adapter->dropForeignKey($tableName, $columns, $constraint);
$end();
}
/**
* @inheritDoc
*/
public function createDatabase(string $name, array $options = []): void
{
$end = $this->startCommandTimer();
$this->writeCommand('createDatabase', [$name]);
parent::createDatabase($name, $options);
$end();
}
/**
* @inheritDoc
*/
public function dropDatabase(string $name): void
{
$end = $this->startCommandTimer();
$this->writeCommand('dropDatabase', [$name]);
parent::dropDatabase($name);
$end();
}
/**
* @inheritDoc
*/
public function createSchema(string $name = 'public'): void
{
$end = $this->startCommandTimer();
$this->writeCommand('createSchema', [$name]);
parent::createSchema($name);
$end();
}
/**
* @inheritDoc
*/
public function dropSchema(string $name): void
{
$end = $this->startCommandTimer();
$this->writeCommand('dropSchema', [$name]);
parent::dropSchema($name);
$end();
}
/**
* @inheritDoc
*/
public function executeActions(Table $table, array $actions): void
{
$end = $this->startCommandTimer();
$this->writeCommand(sprintf('Altering table %s', $table->getName()));
parent::executeActions($table, $actions);
$end();
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
use RuntimeException;
/**
* Exception thrown when a column type doesn't match a Phinx type.
*
* @author Martijn Gastkemper <martijngastkemper@gmail.com>
*/
class UnsupportedColumnTypeException extends RuntimeException
{
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Db\Adapter;
/**
* Wrapper Interface.
*
* @author Woody Gilk <woody.gilk@gmail.com>
*/
interface WrapperInterface
{
/**
* Class constructor, must always wrap another adapter.
*
* @param \Phinx\Db\Adapter\AdapterInterface $adapter Adapter
*/
public function __construct(AdapterInterface $adapter);
/**
* Sets the database adapter to proxy commands to.
*
* @param \Phinx\Db\Adapter\AdapterInterface $adapter Adapter
* @return \Phinx\Db\Adapter\AdapterInterface
*/
public function setAdapter(AdapterInterface $adapter): AdapterInterface;
/**
* Gets the database adapter.
*
* @throws \RuntimeException if the adapter has not been set
* @return \Phinx\Db\Adapter\AdapterInterface
*/
public function getAdapter(): AdapterInterface;
}