データベースドライバー
merqlは接続の転送方式とデータベース方言を分離します。
DatabaseConnection アダプターはPDOまたはmysqli経由で SQL を実行し、Driver はデータベースエンジン固有のメタデータ SQL と識別子の引用符処理を担います。MySQLとSQLite用の組み込みドライバーが用意されています。
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
// Auto-detects MySQL or SQLite from the connection driver identity.
Driverインターフェース
すべてのドライバーは次の5つのメソッドを実装します:
use Merql\Driver\Driver;
interface Driver
{
public function quoteIdentifier(string $name): string;
public function listTables(DatabaseConnection $connection): array;
public function readSchema(DatabaseConnection $connection, string $table): TableSchema;
public function readForeignKeys(DatabaseConnection $connection): array;
public function selectAll(string $table): string;
}
| メソッド | 目的 |
|---|---|
quoteIdentifier |
SQL で使用するテーブル名または列名を引用符で囲みます。 |
listTables |
現在のデータベース内にあるすべてのユーザーテーブルを返します。 |
readSchema |
テーブルの列名、型、主キー、一意キーを読み取ります。 |
readForeignKeys |
子テーブルから親テーブルへの依存関係マップを返します。 |
selectAll |
テーブル用の SELECT * クエリを構築します。 |
MysqlDriver
メタデータの取得には INFORMATION_SCHEMA クエリを使い、識別子はバッククォートで囲みます。
use Merql\Driver\MysqlDriver;
$driver = new MysqlDriver();
$driver->quoteIdentifier('posts');
// `posts`
$driver->quoteIdentifier('my`table');
// `my``table`
$tables = $driver->listTables($connection);
// ['comments', 'posts', 'users']
$schema = $driver->readSchema($connection, 'posts');
// TableSchema with columns, primaryKey, uniqueKeys
$fks = $driver->readForeignKeys($connection);
// ['comments' => ['posts', 'users']]
テーブル一覧の取得では、現在のデータベースと BASE TABLE 型で絞り込んだ INFORMATION_SCHEMA.TABLES をクエリします。スキーマの読み取りでは、列に INFORMATION_SCHEMA.COLUMNS、主キーと一意キーに INFORMATION_SCHEMA.KEY_COLUMN_USAGE をクエリします。
SqliteDriver
メタデータの取得には PRAGMA クエリを使い、識別子は二重引用符で囲みます。
use Merql\Driver\SqliteDriver;
$driver = new SqliteDriver();
$driver->quoteIdentifier('posts');
// "posts"
$driver->quoteIdentifier('my"table');
// "my""table"
$tables = $driver->listTables($connection);
// Queries sqlite_master, excludes sqlite_* internal tables.
$schema = $driver->readSchema($connection, 'posts');
// Uses PRAGMA table_info() and PRAGMA index_list().
$fks = $driver->readForeignKeys($connection);
// Uses PRAGMA foreign_key_list() for each table.
DriverFactory
DriverFactory は DatabaseConnection::driverName() から適切なドライバーを自動検出します。
use Merql\Connection;
use Merql\Driver\DriverFactory;
$connection = Connection::mysql('127.0.0.1', 'mydb', 'root', '');
$driver = DriverFactory::create($connection);
// Returns MysqlDriver
$connection = Connection::sqlite(':memory:');
$driver = DriverFactory::create($connection);
// Returns SqliteDriver
接続ドライバーの識別情報が認識されない場合、メッセージ Unsupported database driver: <name> を持つ RuntimeException がスローされます。merqlにはPostgreSQL用ドライバーは含まれていません。
カスタムドライバーの登録
MySQLとSQLite以外のデータベースでは、Driver を実装するクラスを作成して登録します。以下の PostgresDriver は独自のクラスに置き換えてください:
use Merql\Driver\DriverFactory;
DriverFactory::register('pgsql', PostgresDriver::class);
$connection = Connection::fromDsn('pgsql:host=localhost;dbname=mydb', 'user', 'pass');
$driver = DriverFactory::create($connection);
// Returns your PostgresDriver instance.
ドライバークラスは Driver インターフェースを実装する必要があります。register() の最初の引数は接続ドライバーの識別情報です。
リセット
テスト時にファクトリーをデフォルト状態に戻します:
DriverFactory::reset();
// Reverts to only MySQL and SQLite drivers.
接続ヘルパー
Connection クラスは適切なデフォルト設定でアダプターを構築します。PDOアダプターでは、エラー時の例外、連想配列形式の取得、ネイティブのプリペアドステートメント、文字列化された取得値が使われます。mysqliアダプターは utf8mb4 を設定し、mysqliの例外モードとプリペアドステートメントを使って、取得値を同じ文字列またはnullの形式に正規化します。
use Merql\Connection;
// MySQL.
$connection = Connection::mysql('127.0.0.1', 'my_database', 'root', 'password');
$connection = Connection::mysql('db.example.com', 'mydb', 'user', 'pass', port: 3307);
// MySQLi.
$connection = Connection::mysqli('127.0.0.1', 'my_database', 'root', 'password');
// SQLite.
$connection = Connection::sqlite(':memory:');
$connection = Connection::sqlite('/var/data/app.sqlite');
// Any MySQL or SQLite PDO DSN.
$connection = Connection::fromDsn('mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4', 'user', 'pass');
fromDsn() はPDOが開ける任意のDSNを受け付けますが、merqlでスナップショットの作成と適用を行うには、登録済みドライバーが必要です。pgsql: 接続は(pdo_pgsql がインストールされていれば)開けますが、Merql::init() と Snapshotter、Applier、GuardedApplier のコンストラクターは DriverFactory::create() を呼び出します。ドライバーを登録するか、ドライバーを渡さない限り、RuntimeException: Unsupported database driver: pgsql がスローされます。
Connection::sqlite() は PRAGMA foreign_keys = ON も自動的に有効にします。これはSQLiteで外部キー制約を有効にするために必要です。
ドライバーの使用箇所
merqlではさまざまな箇所でドライバーを使用します:
- Snapshotter は
listTables、readSchema、selectAllを使ってデータベースの状態を取得します。 - Applier は
readForeignKeysを使って操作順を決め、識別子を引用符で囲むためにドライバーをSqlGeneratorに渡します。 - SqlGenerator は
quoteIdentifierを使って安全な SQL を構築します。
ドライバーを指定せずに Snapshotter または Applier に接続を渡すと、DriverFactory::create() が自動的に呼び出されます。