Перейти до вмісту

Драйвери баз даних

merql розділяє транспорт з'єднання та діалект бази даних. Адаптер DatabaseConnection виконує SQL через PDO або mysqli, тоді як Driver обробляє метадані SQL, специфічні для рушія бази даних, та екранування ідентифікаторів. Вбудовані драйвери доступні для MySQL і SQLite.

PHP
use Merql\Driver\DriverFactory;

$driver = DriverFactory::create($connection);
// Auto-detects MySQL or SQLite from the connection driver identity.

Інтерфейс Driver

Кожен драйвер реалізує п'ять методів:

PHP
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, а для ідентифікаторів — екранування зворотними апострофами.

PHP
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, а для ідентифікаторів — екранування подвійними лапками.

PHP
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().

PHP
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 позначає ваш власний клас:

PHP
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() — це ідентифікатор драйвера з'єднання.

Скидання

Для тестування скиньте фабрику до типового стану:

PHP
DriverFactory::reset();
// Reverts to only MySQL and SQLite drivers.

Помічник для з'єднань

Клас Connection створює адаптери з оптимальними типовими параметрами. Адаптери PDO використовують винятки у разі помилки, режим отримання асоціативних масивів, справжню підготовку запитів і перетворення отриманих значень на рядки. Адаптер mysqli задає utf8mb4, використовує режим винятків mysqli, підготовлені запити та нормалізує отримані значення до однакового формату «рядок або null».

PHP
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() викликається автоматично.