---
title: "Base de données et migrations"
description: "Adaptateur de base de données multi-pilote, génération de modèles basée sur le schéma et des migrations SQL numérotées."
---

Nibiru est livré avec **cinq pilotes de base de données** derrière un adaptateur `Db` unifié, ainsi qu'un exécuteur de migration SQL numérotée piloté par la [CLI](/cli/migrations/).

## Choix du pilote

Définissez le pilote actif dans `[DATABASE] driver` de votre fichier INI :

| Pilote | Backend | Notes |
|---|---|---|
| `mysql` | MySQL/MariaDB natif (`mysqli`) | Le plus rapide, sans surcharge PDO. |
| `pdo` | PDO MySQL | Par défaut recommandé. Requêtes préparées, les pilotes sont largement utilisés. |
| `postgres` | PostgreSQL via **ODBC** | Lorsque votre serveur n'a disponible que ODBC. |
| `psql` | PostgreSQL via libpq (`pg_*`) | PostgreSQL natif. |
| `postgresql` | Un wrapper qui choisit le meilleur transport PostgreSQL à l'exécution. | |
```ini
[DATABASE]
driver   = "pdo"
hostname = "localhost"
port     = 3306
username = "nibiru"
password = "secret"
basename = "nibiru_dev"
encoding = "utf8mb4"
is.active = true
```
Le dispatcheur initialise le pilote au démarrage. Changer de pilote nécessite uniquement une modification de la configuration et un redémarrage.

## L'adaptateur Db

Chaque modèle généré étend un adaptateur `Db` spécifique au pilote (`Adapter\MySQL\Db`, `Adapter\PostgreSQL\Db`, `Adapter\Odbc\Db`). Tous les adaptateurs partagent la même interface :
```php
use Nibiru\Pdo;

// Read a single row by primary-key columns
$row = Pdo::fetchRowInArrayById('users', ['user_id' => 42]);

// Run a parameterised query
$rows = Pdo::fetchAll(
    'SELECT * FROM products WHERE category = :cat',
    [':cat' => 'gold-plating']
);

// Insert
Pdo::insert('products', [
    'name' => 'Marduk Gold Plating',
    'price' => 99.0,
]);

// Update
Pdo::update('products',
    ['price' => 89.0],
    ['id' => 1]);

// Delete
Pdo::delete('products', ['id' => 1]);

// Last insert id
Pdo::lastInsertId();
```
Des aidants spécifiques au pilote existent directement dans les classes d'adaptation elles-mêmes (`\Nibiru\Mysql::query()`, `\Nibiru\Postgresql::pgQuery()`, …) lorsque vous avez besoin d'un accès brut.

## Modèles basés sur le schéma

Lorsque `[GENERATOR] database = true`, le dispatcheur régénère une classe PHP par table à chaque requête. Consultez [Modèles](/core/models/).

En production :
```ini
[GENERATOR]
database          = false
database.overwrite = false
```
Regénérez uniquement lorsque vous migrez le schéma.

## Migrations

Les migrations sont des fichiers **SQL simples** dans `application/settings/config/database/`, numérotés pour l'ordre d'exécution :
```
application/settings/config/database/
├── 001-acl.sql
├── 002-account.sql
├── 003-api_registry.sql
├── 004-timeanddate.sql
├── 005-user.sql
├── 006-user_to_account.sql
├── 011-acl-data.sql
├── 012-add-unique-key-user.sql
└── 013-add-account-email.sql
```
La CLI les applique avec :
```bash
./nibiru -mi local
APPLICATION_ENV=staging   ./nibiru -mi staging
APPLICATION_ENV=production ./nibiru -mi production
```
Le lanceur crée une table `_migrations` (par nom de pilote) et ignore les fichiers déjà appliqués. Chaque fichier s'exécute en tant que lot unique ; si une instruction échoue au milieu du processus, corrigez le SQL et relancez l'opération.

### Conventions de nommage des fichiers

- Préfixe numérique à trois chiffres avec zéro-padding : `NNN-<slug>.sql`.
- Les slugs décrivent le changement (`-add-account-email`, `-drop-wrong-constraints`).
- Un seul changement logique par fichier. Ne pas squasher.
- Pour les seeds contenant uniquement des données, utilisez le suffixe `-data.sql` (`011-acl-data.sql`).

### Idempotence

Utilisez `IF NOT EXISTS` et `IF EXISTS` pour que les fichiers puissent être relancés en toute sécurité :
```sql
CREATE TABLE IF NOT EXISTS api_registry (
    api_registry_id     INT(11) NOT NULL AUTO_INCREMENT,
    api_registry_name   VARCHAR(255) NOT NULL,
    api_registry_token  VARCHAR(64)  NOT NULL,
    PRIMARY KEY (api_registry_id),
    UNIQUE KEY api_registry_token_uk (api_registry_token)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
``````sql
ALTER TABLE user
    ADD UNIQUE KEY user_login_uk (user_login)
    /* skip if exists; on MySQL 8 you can wrap with IF NOT EXISTS */;
```
### Commandes de réinitialisation (utiliser avec prudence)
```bash
./nibiru -mi-reset local                    # forget all applied migrations
./nibiru -mi-reset-file 005-user.sql local  # forget a single file's run record
```
Ces commandes ne suppriment pas les tables — uniquement la table d'audit `_migrations`. Combinez avec un `DROP` manuel si vous voulez vraiment une situation propre.

## Spécificités de PostgreSQL

Lorsque `driver = "psql"` ou `"postgresql"` :

- Utilisez `SERIAL` / `BIGSERIAL` au lieu de `AUTO_INCREMENT`.
- Les tables dans `information_schema.tables` plutôt que `SHOW TABLES`.
- Citation : les identifiants sont entre guillemets doubles (`"user"` est la forme correcte car `user` est réservé).
- Le drapeau de compilation conditionnelle dans l'interface CLI signifie que PostgreSQL se dégrade gracieusement si libpq n'est pas présent au moment de la compilation — vérifiez `./nibiru -v` pour confirmer le support.

## Pooling des connexions

Il n'y a pas de piscine intégrée. Pour les applications à forte charge, utilisez :

- **MariaDB / MySQL :** ProxySQL ou HAProxy devant la base de données.
- **PostgreSQL :** PgBouncer en mode de poolisation des transactions.

Nibiru ouvre une connexion par requête, donc un pooler est généralement tout ce dont vous avez besoin.

## Tracas communes

- **`is.active = false`** désactive silencieusement les connexions — vérifiez cela lorsque les requêtes retournent `null`.
- **Générateur activé en production.** Avec `[GENERATOR] database = true`, chaque requête réécrit vos fichiers de modèle. Éteignez-le après les déploiements.
- **Pilotes mélangés.** Choisir `mysql` lors de l'exécution de PostgreSQL vous donne un `Pdo::fetchAll` réussi qui retourne `[]` — la connexion échoue silencieusement. Vérifiez toujours avec une requête `SELECT 1` dans un test fumeur.
