
# Adatbázis-illesztőprogramok

A merql különválasztja a kapcsolatátvitelt az adatbázis-dialektustól. Egy
`DatabaseConnection` adapter SQL-utasításokat hajt végre PDO-n vagy mysqli-n keresztül, míg egy `Driver`
adatbázismotor-specifikus metaadatokat SQL kezel, és gondoskodik az azonosítók idézőjelezéséről. Beépített illesztőprogramok állnak rendelkezésre ehhez: MySQL és SQLite.

```php
use Merql\Driver\DriverFactory;

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

## A Driver interfész

Minden illesztőprogram öt metódust valósít meg:

```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;
}
```

| Metódus | Cél |
|---|---|
| `quoteIdentifier` | Táblanév vagy oszlopnév idézőjelezése SQL-ban való használathoz. |
| `listTables` | Az aktuális adatbázis összes felhasználói táblájának visszaadása. |
| `readSchema` | Egy tábla oszlopneveinek, típusainak, elsődleges kulcsának és egyedi kulcsainak beolvasása. |
| `readForeignKeys` | A gyermek- és szülőtáblák közötti függőségi térkép visszaadása. |
| `selectAll` | `SELECT *` lekérdezés összeállítása egy táblához. |

## MysqlDriver

Metaadatokhoz `INFORMATION_SCHEMA`-lekérdezéseket, azonosítókhoz pedig backtick idézőjelezést használ.

```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']]
```

A táblalista-lekérdezések az `INFORMATION_SCHEMA.TABLES` alapján, az aktuális adatbázisra és az `BASE TABLE` típusra szűrve kérdezik le a táblákat. A séma beolvasásakor az oszlopokhoz az `INFORMATION_SCHEMA.COLUMNS`, az elsődleges és egyedi kulcsokhoz pedig az `INFORMATION_SCHEMA.KEY_COLUMN_USAGE` adatai szolgálnak.

## SqliteDriver

Metaadatokhoz `PRAGMA`-lekérdezéseket, azonosítókhoz pedig dupla idézőjeles idézőjelezést használ.

```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

A `DriverFactory` automatikusan felismeri a megfelelő illesztőprogramot az `DatabaseConnection::driverName()` alapján.

```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
```

Ha a kapcsolat illesztőprogram-azonosítója nem felismerhető, a rendszer egy `RuntimeException` elemet dob a következő üzenettel: `Unsupported database driver: <name>`. A merql nem tartalmaz PostgreSQL illesztőprogramot.

### Egyéni illesztőprogramok regisztrálása

A MySQL és SQLite mellett más adatbázisokhoz írjon egy `Driver` megvalósító osztályt, majd regisztrálja azt. Az alábbi `PostgresDriver` a saját osztályát jelöli:

```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.
```

Az illesztőprogram osztályának meg kell valósítania a `Driver` interfészt. A `register()` első argumentuma a kapcsolat illesztőprogram-azonosítója.

### Visszaállítás

Teszteléshez állítsa vissza a gyárat az alapértelmezett állapotára:

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

## Kapcsolatsegéd

A `Connection` osztály ésszerű alapértelmezésekkel hoz létre adaptereket. A PDO-adapterek hiba esetén kivételt dobnak, asszociatív beolvasási módot, valódi előkészített utasításokat és karakterlánccá alakított beolvasott értékeket használnak. A mysqli-adapter beállítja a `utf8mb4` értékét, mysqli-kivételmódot és előkészített utasításokat használ, a beolvasott értékeket pedig ugyanarra a karakterlánc vagy null alakra normalizálja.

```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');
```

A `fromDsn()` bármilyen, a PDO által megnyitható DSN-t elfogad, a merql viszont csak regisztrált illesztőprogramon keresztül tud pillanatképet készíteni és alkalmazni. Egy `pgsql:` kapcsolat megnyílik (ha telepítve van a `pdo_pgsql`), de a `Merql::init()`, valamint a `Snapshotter`, `Applier` és `GuardedApplier` konstruktorai a `DriverFactory::create()` metódust hívják meg, amely `RuntimeException: Unsupported database driver: pgsql` hibát dob, kivéve ha [illesztőprogramot regisztrált](#registering-custom-drivers) hozzá, vagy átad egyet.

A `Connection::sqlite()` automatikusan engedélyezi a `PRAGMA foreign_keys = ON` használatát is, amelyre a SQLite-nak szüksége van az idegen kulcsok érvényesítéséhez.

## Az illesztőprogramok használata

A merql számos pontján használ illesztőprogramokat:

- **Snapshotter** az `listTables`, `readSchema` és `selectAll` használatával rögzíti az adatbázis állapotát.
- **Applier** az `readForeignKeys` használatával határozza meg a műveletek sorrendjét, az azonosítók idézőjelezéséhez pedig átadja az illesztőprogramot a `SqlGenerator` számára.
- **SqlGenerator** az `quoteIdentifier` használatával állít össze biztonságos SQL-t.

Ha illesztőprogram megadása nélkül ad át kapcsolatot a `Snapshotter` vagy a `Applier` számára, a rendszer automatikusan meghívja a `DriverFactory::create()`-t.
