Drivers de banco de dados
merql separa o transporte da conexão do dialeto do banco de dados. Um adaptador DatabaseConnection executa SQL via PDO ou mysqli, enquanto um Driver lida com metadados SQL específicos do mecanismo de banco de dados e com a citação de identificadores. Há drivers integrados para MySQL e SQLite.
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
// Auto-detects MySQL or SQLite from the connection driver identity.
A interface Driver
Cada driver implementa cinco métodos:
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;
}
| Método | Finalidade |
|---|---|
quoteIdentifier |
Coloca entre aspas o nome de uma tabela ou coluna para uso em SQL. |
listTables |
Retorna todas as tabelas de usuário no banco de dados atual. |
readSchema |
Lê os nomes e tipos das colunas, a chave primária e as chaves exclusivas de uma tabela. |
readForeignKeys |
Retorna um mapa das dependências entre tabelas filhas e tabelas pai. |
selectAll |
Cria uma consulta SELECT * para uma tabela. |
MysqlDriver
Usa consultas INFORMATION_SCHEMA para os metadados e aspas invertidas para delimitar identificadores.
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']]
As consultas de listagem de tabelas usam INFORMATION_SCHEMA.TABLES filtrado pelo banco de dados atual e pelo tipo BASE TABLE. As consultas de leitura do esquema usam INFORMATION_SCHEMA.COLUMNS para as colunas e INFORMATION_SCHEMA.KEY_COLUMN_USAGE para as chaves primárias e exclusivas.
SqliteDriver
Usa consultas PRAGMA para os metadados e aspas duplas para delimitar identificadores.
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 detecta automaticamente o driver correto a partir de 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
Se a identidade do driver da conexão não for reconhecida, será lançado um RuntimeException com a mensagem Unsupported database driver: <name>. merql não inclui um driver PostgreSQL.
Registrando drivers personalizados
Para bancos de dados além de MySQL e SQLite, escreva uma classe que implemente Driver e registre-a. PostgresDriver abaixo representa sua própria classe:
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.
A classe do driver deve implementar a interface Driver. O primeiro argumento de register() é a identidade do driver da conexão.
Redefinição
Para testar, redefina a fábrica para seu estado padrão:
DriverFactory::reset();
// Reverts to only MySQL and SQLite drivers.
Auxiliar de conexão
A classe Connection cria adaptadores com padrões sensatos. Os adaptadores PDO usam exceções em caso de erro, modo de busca associativo, prepared statements reais e valores buscados convertidos em strings. O adaptador mysqli define utf8mb4, usa o modo de exceção do mysqli, prepared statements e normaliza os valores buscados para o mesmo formato de string ou 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() aceita qualquer DSN que o PDO possa abrir, mas merql só consegue criar snapshots e aplicar alterações por meio de um driver registrado. Uma conexão pgsql: é aberta (quando pdo_pgsql estiver instalado), mas os construtores Merql::init(), Snapshotter, Applier e GuardedApplier chamam DriverFactory::create(), que lança RuntimeException: Unsupported database driver: pgsql, a menos que você tenha registrado um driver para ela ou informe um.
Connection::sqlite() também ativa PRAGMA foreign_keys = ON automaticamente, requisito de SQLite para aplicar restrições de chaves estrangeiras.
Onde os drivers são usados
Os drivers são usados em todo o merql:
- Snapshotter usa
listTables,readSchemaeselectAllpara capturar o estado do banco de dados. - Applier usa
readForeignKeyspara determinar a ordem das operações e passa o driver paraSqlGeneratorpara citar identificadores. - SqlGenerator usa
quoteIdentifierpara criar SQL seguros.
Se você passar uma conexão para Snapshotter ou Applier sem especificar um driver, DriverFactory::create() será chamado automaticamente.