Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Adapter classes to use Connection pt1 #694

Merged
merged 10 commits into from
Feb 26, 2024
12 changes: 1 addition & 11 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,13 @@ parameters:
count: 2
path: src/Db/Adapter/MysqlAdapter.php

-
message: "#^Parameter \\#4 \\$options of method Migrations\\\\Db\\\\Adapter\\\\PdoAdapter\\:\\:createPdoConnection\\(\\) expects array\\<int, mixed\\>, array\\<int\\|string, mixed\\> given\\.$#"
count: 1
path: src/Db/Adapter/MysqlAdapter.php

-
message: "#^Right side of && is always true\\.$#"
count: 1
path: src/Db/Adapter/MysqlAdapter.php

-
message: "#^Access to an undefined property PDO\\:\\:\\$connection\\.$#"
message: "#^Access to an undefined property Cake\\\\Database\\\\Connection\\:\\:\\$connection\\.$#"
count: 1
path: src/Db/Adapter/PdoAdapter.php

Expand All @@ -60,11 +55,6 @@ parameters:
count: 1
path: src/Db/Adapter/SqlserverAdapter.php

-
message: "#^Parameter \\#4 \\$options of method Migrations\\\\Db\\\\Adapter\\\\PdoAdapter\\:\\:createPdoConnection\\(\\) expects array\\<int, mixed\\>, array\\<int\\|string, mixed\\> given\\.$#"
count: 1
path: src/Db/Adapter/SqlserverAdapter.php

-
message: "#^Ternary operator condition is always true\\.$#"
count: 2
Expand Down
7 changes: 2 additions & 5 deletions src/Command/StatusCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,9 @@ protected function getConfig(Arguments $args): Config
$adapter = $connectionConfig['scheme'] ?? null;
$adapterConfig = [
'adapter' => $adapter,
'user' => $connectionConfig['username'],
'pass' => $connectionConfig['password'],
'host' => $connectionConfig['host'],
'name' => $connectionConfig['database'],
'migration_table' => $table,
'connection' => $connectionName,
'database' => $connectionConfig['database'],
'migration_table' => $table,
];

$configData = [
Expand Down
132 changes: 33 additions & 99 deletions src/Db/Adapter/MysqlAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,14 @@
namespace Migrations\Db\Adapter;

use Cake\Database\Connection;
use Cake\Database\Driver\Mysql as MysqlDriver;
use InvalidArgumentException;
use Migrations\Db\AlterInstructions;
use Migrations\Db\Literal;
use Migrations\Db\Table\Column;
use Migrations\Db\Table\ForeignKey;
use Migrations\Db\Table\Index;
use Migrations\Db\Table\Table;
use PDO;
use Phinx\Config\FeatureFlags;
use RuntimeException;
use UnexpectedValueException;

/**
* Phinx MySQL Adapter.
Expand Down Expand Up @@ -102,71 +98,26 @@
*/
public function connect(): void
{
if ($this->connection === null) {
if (!class_exists('PDO') || !in_array('mysql', PDO::getAvailableDrivers(), true)) {
// @codeCoverageIgnoreStart
throw new RuntimeException('You need to enable the PDO_Mysql extension for Phinx to run properly.');
// @codeCoverageIgnoreEnd
}

$options = $this->getOptions();

$dsn = 'mysql:';

if (!empty($options['unix_socket'])) {
// use socket connection
$dsn .= 'unix_socket=' . $options['unix_socket'];
} else {
// use network connection
$dsn .= 'host=' . $options['host'];
if (!empty($options['port'])) {
$dsn .= ';port=' . $options['port'];
}
}

$dsn .= ';dbname=' . $options['name'];

// charset support
if (!empty($options['charset'])) {
$dsn .= ';charset=' . $options['charset'];
}

$driverOptions = [];

// use custom data fetch mode
if (!empty($options['fetch_mode'])) {
$driverOptions[PDO::ATTR_DEFAULT_FETCH_MODE] = constant('\PDO::FETCH_' . strtoupper($options['fetch_mode']));
}

// pass \PDO::ATTR_PERSISTENT to driver options instead of useless setting it after instantiation
if (isset($options['attr_persistent'])) {
$driverOptions[PDO::ATTR_PERSISTENT] = $options['attr_persistent'];
}

// support arbitrary \PDO::MYSQL_ATTR_* driver options and pass them to PDO
// https://php.net/manual/en/ref.pdo-mysql.php#pdo-mysql.constants
foreach ($options as $key => $option) {
if (strpos($key, 'mysql_attr_') === 0) {
$pdoConstant = '\PDO::' . strtoupper($key);
if (!defined($pdoConstant)) {
throw new UnexpectedValueException('Invalid PDO attribute: ' . $key . ' (' . $pdoConstant . ')');
}
$driverOptions[constant($pdoConstant)] = $option;
}
}
$this->getConnection()->getDriver()->connect();
$this->setConnection($this->getConnection());
}

$db = $this->createPdoConnection($dsn, $options['user'] ?? null, $options['pass'] ?? null, $driverOptions);
/**
* @inheritDoc
*/
public function setConnection(Connection $connection): AdapterInterface
{
$connection->execute(sprintf('USE %s', $this->getOption('database')));

$this->setConnection($db);
}
return parent::setConnection($connection);
}

/**
* @inheritDoc
*/
public function disconnect(): void
{
$this->connection = null;
$this->getConnection()->getDriver()->disconnect();
}

/**
Expand All @@ -182,23 +133,23 @@
*/
public function beginTransaction(): void
{
$this->execute('START TRANSACTION');
$this->getConnection()->begin();
}

/**
* @inheritDoc
*/
public function commitTransaction(): void
{
$this->execute('COMMIT');
$this->getConnection()->commit();
}

/**
* @inheritDoc
*/
public function rollbackTransaction(): void
{
$this->execute('ROLLBACK');
$this->getConnection()->rollback();

Check warning on line 152 in src/Db/Adapter/MysqlAdapter.php

View check run for this annotation

Codecov / codecov/patch

src/Db/Adapter/MysqlAdapter.php#L152

Added line #L152 was not covered by tests
}

/**
Expand Down Expand Up @@ -237,7 +188,7 @@

$options = $this->getOptions();

return $this->hasTableWithSchema($options['name'], $tableName);
return $this->hasTableWithSchema($options['database'], $tableName);
}

/**
Expand All @@ -247,15 +198,15 @@
*/
protected function hasTableWithSchema(string $schema, string $tableName): bool
{
$result = $this->fetchRow(sprintf(
$connection = $this->getConnection();
$result = $connection->execute(
"SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'",
$schema,
$tableName
));
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
[$schema, $tableName]
);

return !empty($result);
return $result->rowCount() === 1;
}

/**
Expand Down Expand Up @@ -318,7 +269,7 @@

// set the table comment
if (isset($options['comment'])) {
$optionsStr .= sprintf(' COMMENT=%s ', $this->getConnection()->quote($options['comment']));
$optionsStr .= sprintf(' COMMENT=%s ', $this->quoteString($options['comment']));
}

// set the table row format
Expand Down Expand Up @@ -406,7 +357,7 @@

// passing 'null' is to remove table comment
$newComment = $newComment ?? '';
$sql = sprintf(' COMMENT=%s ', $this->getConnection()->quote($newComment));
$sql = sprintf(' COMMENT=%s ', $this->quoteString($newComment));
$instructions->addAlter($sql);

return $instructions;
Expand Down Expand Up @@ -797,7 +748,7 @@
WHERE t.CONSTRAINT_TYPE='PRIMARY KEY'
AND t.TABLE_SCHEMA='%s'
AND t.TABLE_NAME='%s'",
$options['name'],
$options['database'],
$tableName
));

Expand Down Expand Up @@ -1298,6 +1249,7 @@
} else {
$this->execute(sprintf('CREATE DATABASE `%s` DEFAULT CHARACTER SET `%s`', $name, $charset));
}
$this->execute(sprintf('USE %s', $name));
}

/**
Expand Down Expand Up @@ -1356,7 +1308,7 @@
// we special case NULL as it's not actually allowed an enum value,
// and we want MySQL to issue an error on the create statement, but
// quote coerces it to an empty string, which will not error
return $value === null ? 'NULL' : $this->getConnection()->quote($value);
return $value === null ? 'NULL' : $this->quoteString($value);
}, $values)) . ')';
}

Expand All @@ -1365,8 +1317,10 @@
$def .= !$column->isSigned() && isset($this->signedColumnTypes[(string)$column->getType()]) ? ' unsigned' : '';
$def .= $column->isNull() ? ' NULL' : ' NOT NULL';

$connection = $this->getConnection();
$version = $connection->getDriver()->version();
if (
version_compare($this->getAttribute(PDO::ATTR_SERVER_VERSION), '8', '>=')
version_compare($version, '8', '>=')
&& in_array($column->getType(), static::PHINX_TYPES_GEOSPATIAL)
&& !is_null($column->getSrid())
) {
Expand All @@ -1378,7 +1332,7 @@
$default = $column->getDefault();
// MySQL 8 supports setting default for the following tested types, but only if they are "cast as expressions"
if (
version_compare($this->getAttribute(PDO::ATTR_SERVER_VERSION), '8', '>=') &&
version_compare($version, '8', '>=') &&
is_string($default) &&
in_array(
$column->getType(),
Expand All @@ -1388,12 +1342,12 @@
)
)
) {
$default = Literal::from('(' . $this->getConnection()->quote($column->getDefault()) . ')');
$default = Literal::from('(' . $this->quoteString($column->getDefault()) . ')');
}
$def .= $this->getDefaultValueDefinition($default, (string)$column->getType());

if ($column->getComment()) {
$def .= ' COMMENT ' . $this->getConnection()->quote((string)$column->getComment());
$def .= ' COMMENT ' . $this->quoteString((string)$column->getComment());
}

if ($column->getUpdate()) {
Expand Down Expand Up @@ -1508,7 +1462,7 @@
FROM information_schema.tables
WHERE table_schema = '%s'
AND table_name = '%s'",
$options['name'],
$options['database'],
$tableName
);

Expand All @@ -1526,24 +1480,4 @@
{
return array_merge(parent::getColumnTypes(), static::$specificColumnTypes);
}

/**
* @inheritDoc
*/
public function getDecoratedConnection(): Connection
{
if (isset($this->decoratedConnection)) {
return $this->decoratedConnection;
}

$options = $this->getOptions();
$options = [
'username' => $options['user'] ?? null,
'password' => $options['pass'] ?? null,
'database' => $options['name'],
'quoteIdentifiers' => true,
] + $options;

return $this->decoratedConnection = $this->buildConnection(MysqlDriver::class, $options);
}
}
Loading
Loading