Драйвери баз даних
merql розділяє транспорт з'єднання та діалект бази даних. Адаптер DatabaseConnection виконує SQL через PDO або mysqli, тоді як Driver обробляє метадані SQL, специфічні для рушія бази даних, та екранування ідентифікаторів. Вбудовані драйвери доступні для MySQL і SQLite.
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
// Auto-detects MySQL or SQLite from the connection driver identity.
Інтерфейс Driver
Кожен драйвер реалізує п'ять методів:
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']]
Для отримання списку таблиць виконує запити INFORMATION_SCHEMA.TABLES з фільтрацією за поточною базою даних і типом BASE TABLE. Для читання схеми запитує стовпці через 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
Якщо ідентифікатор драйвера з'єднання не розпізнано, викидається RuntimeException з повідомленням Unsupported database driver: <name>. 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() приймає будь-який DSN, який може відкрити PDO, але 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() викликається автоматично.