fix(db): suivi seeds unifie + idempotence DDL + doc trou 0004 (#111)
All checks were successful
CI / secret-scan (push) Successful in 20s
CI / php-lint (push) Successful in 31s
CI / static-tests (push) Successful in 1m30s
CI / js-tests (push) Successful in 33s

This commit is contained in:
Corentin JOGUET 2026-06-25 10:58:39 +02:00
parent a6dcb31c16
commit ba2abbfae9
6 changed files with 124 additions and 43 deletions

View file

@ -8,21 +8,51 @@ Transcription executable du MLD (`docs/merise/mld.md`, 21 tables) vers MariaDB 1
db/ db/
migrations/ migrations SQL versionnees, appliquees dans l'ordre lexicographique migrations/ migrations SQL versionnees, appliquees dans l'ordre lexicographique
0001_init_schema.sql schema initial : 21 tables, FK, CHECK, index (InnoDB, utf8mb4) 0001_init_schema.sql schema initial : 21 tables, FK, CHECK, index (InnoDB, utf8mb4)
seeds/ donnees de demonstration (a venir : roles/permissions, allergenes, catalogue) seeds/ donnees de reference (RBAC, allergenes, catalogue, variantes)
migrate.sh runner de migrations (idempotent) migrate-container.sh runner de boot IN-CONTAINER (canonique, service wakdo-migrate)
migrate.sh runner de migrations cote HOTE (manuel, via docker exec)
seed.sh runner de seeds cote HOTE (manuel, via docker exec)
``` ```
## Appliquer les migrations ## Numerotation des migrations (trou 0004 assume)
Les migrations sautent `0004` : la sequence est `0001, 0002, 0003, 0005, 0006,
0007`. Ce n'est PAS un fichier manquant mais un desalignement historique assume :
le numero `0004` a ete consomme cote `seeds/` (`0004_menu_side_maxi.sql`) lors
d'un meme increment de travail, sans contrepartie cote `migrations/`. Le suivi se
fait par NOM DE FICHIER (`schema_migrations`), pas par numero contigu : le trou
est donc inoffensif (rien ne presuppose une sequence sans lacune). Convention
conservee : ne pas reattribuer `0004` cote migrations pour eviter toute confusion
avec le seed homonyme ; la prochaine migration prend le numero suivant disponible.
## Appliquer les migrations + seeds
Chemin canonique (boot de la stack) : le service one-shot `wakdo-migrate`
(`docker compose up`) execute `db/migrate-container.sh`, qui applique
`db/migrations/*.sql` (suivi : table `schema_migrations`) PUIS `db/seeds/*.sql`
(suivi : table `seeds_applied`), de maniere idempotente. Il se connecte a
`wakdo-db` par le reseau compose.
Chemin manuel (hote, via `docker exec`) :
```bash ```bash
bash db/migrate.sh # applique les migrations en attente bash db/migrate.sh # applique les migrations en attente
bash db/migrate.sh --status # liste l'etat sans rien appliquer bash db/migrate.sh --status # liste l'etat des migrations sans rien appliquer
bash db/seed.sh # charge les seeds en attente
bash db/seed.sh --status # liste l'etat des seeds sans rien charger
``` ```
Le runner cible le conteneur `wakdo-db` et lit les identifiants dans `.env` Les runners hote ciblent le conteneur `wakdo-db` et lisent les identifiants dans
(`DB_NAME`, `DB_ROOT_PASSWORD`). Il maintient une table `schema_migrations` `.env` (`DB_NAME`, `DB_ROOT_PASSWORD`).
(une ligne par fichier applique) : relancer ne rejoue que les nouvelles
migrations. La cible `bash db/migrate.sh` est destinee a appeler ce script. ### Suivi partage entre les deux chemins
Les runners hote et conteneur partagent les MEMES tables de suivi (memes noms,
memes colonnes `filename` / `applied_at`) : `schema_migrations` pour les
migrations, `seeds_applied` pour les seeds. Consequence : rejouer un chemin apres
l'autre ne replaye RIEN. (Auparavant `db/seed.sh` suivait une table distincte
`seed_history`, ce qui pouvait lui faire re-jouer des seeds deja charges par
`wakdo-migrate` et echouer sur une contrainte UNIQUE — corrige.)
## Conventions ## Conventions

View file

@ -18,6 +18,12 @@
-- the application layer. -- the application layer.
-- - No CREATE DATABASE / USE here: the target DB is chosen by the runner. -- - No CREATE DATABASE / USE here: the target DB is chosen by the runner.
-- - No seed / INSERT data here (see db/seeds/0001_demo_data.sql). -- - No seed / INSERT data here (see db/seeds/0001_demo_data.sql).
--
-- Idempotence (defense en profondeur, suivi par schema_migrations) : chaque table
-- est creee en CREATE TABLE IF NOT EXISTS. Index, cles uniques et contraintes
-- (FK / CHECK) sont declares INLINE dans le CREATE TABLE : ils ne sont donc pas
-- re-joues quand la table preexiste. Re-jouer ce fichier sur une base deja
-- migree ne modifie pas le schema (aucun ALTER autonome).
-- ============================================================================= -- =============================================================================
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
@ -29,7 +35,7 @@ SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.1 category — root table for the Catalogue sub-domain (no FK) -- 4.1 category — root table for the Catalogue sub-domain (no FK)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE category ( CREATE TABLE IF NOT EXISTS category (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(60) NOT NULL, name VARCHAR(60) NOT NULL,
slug VARCHAR(60) NOT NULL, slug VARCHAR(60) NOT NULL,
@ -46,7 +52,7 @@ CREATE TABLE category (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.6 ingredient — root table for Ingredients & Stock (no FK) -- 4.6 ingredient — root table for Ingredients & Stock (no FK)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE ingredient ( CREATE TABLE IF NOT EXISTS ingredient (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(120) NOT NULL, name VARCHAR(120) NOT NULL,
unit VARCHAR(40) NOT NULL, unit VARCHAR(40) NOT NULL,
@ -71,7 +77,7 @@ CREATE TABLE ingredient (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.8 allergen — reference table (INCO EU 1169/2011), no FK -- 4.8 allergen — reference table (INCO EU 1169/2011), no FK
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE allergen ( CREATE TABLE IF NOT EXISTS allergen (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
code VARCHAR(30) NOT NULL, code VARCHAR(30) NOT NULL,
name VARCHAR(80) NOT NULL, name VARCHAR(80) NOT NULL,
@ -83,7 +89,7 @@ CREATE TABLE allergen (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.10 role — root table for RBAC (no FK) -- 4.10 role — root table for RBAC (no FK)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE role ( CREATE TABLE IF NOT EXISTS role (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
code VARCHAR(40) NOT NULL, code VARCHAR(40) NOT NULL,
label VARCHAR(80) NOT NULL, label VARCHAR(80) NOT NULL,
@ -100,7 +106,7 @@ CREATE TABLE role (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.13 permission — reference table, catalogue frozen at 23 codes (no FK) -- 4.13 permission — reference table, catalogue frozen at 23 codes (no FK)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE permission ( CREATE TABLE IF NOT EXISTS permission (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
code VARCHAR(60) NOT NULL, code VARCHAR(60) NOT NULL,
label VARCHAR(120) NOT NULL, label VARCHAR(120) NOT NULL,
@ -113,7 +119,7 @@ CREATE TABLE permission (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.21 login_throttle — per-source-IP brute-force throttle (no FK) -- 4.21 login_throttle — per-source-IP brute-force throttle (no FK)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE login_throttle ( CREATE TABLE IF NOT EXISTS login_throttle (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
ip_address VARCHAR(45) NOT NULL, ip_address VARCHAR(45) NOT NULL,
failed_attempts SMALLINT UNSIGNED NOT NULL DEFAULT 0, failed_attempts SMALLINT UNSIGNED NOT NULL DEFAULT 0,
@ -128,7 +134,7 @@ CREATE TABLE login_throttle (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.2 product — depends on category -- 4.2 product — depends on category
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE product ( CREATE TABLE IF NOT EXISTS product (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
category_id INT UNSIGNED NOT NULL, category_id INT UNSIGNED NOT NULL,
name VARCHAR(120) NOT NULL, name VARCHAR(120) NOT NULL,
@ -151,7 +157,7 @@ CREATE TABLE product (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.3 menu — depends on category, product -- 4.3 menu — depends on category, product
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE menu ( CREATE TABLE IF NOT EXISTS menu (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
category_id INT UNSIGNED NOT NULL, category_id INT UNSIGNED NOT NULL,
burger_product_id INT UNSIGNED NOT NULL, burger_product_id INT UNSIGNED NOT NULL,
@ -177,7 +183,7 @@ CREATE TABLE menu (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.4 menu_slot — depends on menu (no audit fields) -- 4.4 menu_slot — depends on menu (no audit fields)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE menu_slot ( CREATE TABLE IF NOT EXISTS menu_slot (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
menu_id INT UNSIGNED NOT NULL, menu_id INT UNSIGNED NOT NULL,
name VARCHAR(80) NOT NULL, name VARCHAR(80) NOT NULL,
@ -194,7 +200,7 @@ CREATE TABLE menu_slot (
-- 4.5 menu_slot_option — pure join table, composite PK -- 4.5 menu_slot_option — pure join table, composite PK
-- depends on menu_slot, product -- depends on menu_slot, product
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE menu_slot_option ( CREATE TABLE IF NOT EXISTS menu_slot_option (
menu_slot_id INT UNSIGNED NOT NULL, menu_slot_id INT UNSIGNED NOT NULL,
product_id INT UNSIGNED NOT NULL, product_id INT UNSIGNED NOT NULL,
PRIMARY KEY (menu_slot_id, product_id), PRIMARY KEY (menu_slot_id, product_id),
@ -209,7 +215,7 @@ CREATE TABLE menu_slot_option (
-- 4.7 product_ingredient — join table with attributes, composite PK -- 4.7 product_ingredient — join table with attributes, composite PK
-- depends on product, ingredient -- depends on product, ingredient
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE product_ingredient ( CREATE TABLE IF NOT EXISTS product_ingredient (
product_id INT UNSIGNED NOT NULL, product_id INT UNSIGNED NOT NULL,
ingredient_id INT UNSIGNED NOT NULL, ingredient_id INT UNSIGNED NOT NULL,
quantity_normal SMALLINT UNSIGNED NOT NULL DEFAULT 1, quantity_normal SMALLINT UNSIGNED NOT NULL DEFAULT 1,
@ -232,7 +238,7 @@ CREATE TABLE product_ingredient (
-- 4.9 ingredient_allergen — pure join table, composite PK -- 4.9 ingredient_allergen — pure join table, composite PK
-- depends on ingredient, allergen -- depends on ingredient, allergen
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE ingredient_allergen ( CREATE TABLE IF NOT EXISTS ingredient_allergen (
ingredient_id INT UNSIGNED NOT NULL, ingredient_id INT UNSIGNED NOT NULL,
allergen_id INT UNSIGNED NOT NULL, allergen_id INT UNSIGNED NOT NULL,
PRIMARY KEY (ingredient_id, allergen_id), PRIMARY KEY (ingredient_id, allergen_id),
@ -246,7 +252,7 @@ CREATE TABLE ingredient_allergen (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.11 user — depends on role -- 4.11 user — depends on role
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE user ( CREATE TABLE IF NOT EXISTS user (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
email VARCHAR(254) NOT NULL, email VARCHAR(254) NOT NULL,
password_hash VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL,
@ -275,7 +281,7 @@ CREATE TABLE user (
-- 4.12 role_visible_source — pure join table, composite PK -- 4.12 role_visible_source — pure join table, composite PK
-- depends on role -- depends on role
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE role_visible_source ( CREATE TABLE IF NOT EXISTS role_visible_source (
role_id INT UNSIGNED NOT NULL, role_id INT UNSIGNED NOT NULL,
source ENUM('kiosk','counter','drive') NOT NULL, source ENUM('kiosk','counter','drive') NOT NULL,
PRIMARY KEY (role_id, source), PRIMARY KEY (role_id, source),
@ -287,7 +293,7 @@ CREATE TABLE role_visible_source (
-- 4.14 role_permission — pure join table, composite PK -- 4.14 role_permission — pure join table, composite PK
-- depends on role, permission -- depends on role, permission
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE role_permission ( CREATE TABLE IF NOT EXISTS role_permission (
role_id INT UNSIGNED NOT NULL, role_id INT UNSIGNED NOT NULL,
permission_id INT UNSIGNED NOT NULL, permission_id INT UNSIGNED NOT NULL,
PRIMARY KEY (role_id, permission_id), PRIMARY KEY (role_id, permission_id),
@ -301,7 +307,7 @@ CREATE TABLE role_permission (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.15 customer_order — depends on user (acting_user_id) -- 4.15 customer_order — depends on user (acting_user_id)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE customer_order ( CREATE TABLE IF NOT EXISTS customer_order (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
order_number VARCHAR(20) NOT NULL, order_number VARCHAR(20) NOT NULL,
idempotency_key VARCHAR(36) NULL, idempotency_key VARCHAR(36) NULL,
@ -336,7 +342,7 @@ CREATE TABLE customer_order (
-- 4.16 order_item — depends on customer_order, product, menu -- 4.16 order_item — depends on customer_order, product, menu
-- polymorphic line (product XOR menu) -- polymorphic line (product XOR menu)
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE order_item ( CREATE TABLE IF NOT EXISTS order_item (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
order_id INT UNSIGNED NOT NULL, order_id INT UNSIGNED NOT NULL,
item_type ENUM('product','menu') NOT NULL, item_type ENUM('product','menu') NOT NULL,
@ -370,7 +376,7 @@ CREATE TABLE order_item (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.17 order_item_selection — depends on order_item, menu_slot, product -- 4.17 order_item_selection — depends on order_item, menu_slot, product
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE order_item_selection ( CREATE TABLE IF NOT EXISTS order_item_selection (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
order_item_id INT UNSIGNED NOT NULL, order_item_id INT UNSIGNED NOT NULL,
menu_slot_id INT UNSIGNED NOT NULL, menu_slot_id INT UNSIGNED NOT NULL,
@ -391,7 +397,7 @@ CREATE TABLE order_item_selection (
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- 4.18 order_item_modifier — depends on order_item, ingredient -- 4.18 order_item_modifier — depends on order_item, ingredient
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE order_item_modifier ( CREATE TABLE IF NOT EXISTS order_item_modifier (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
order_item_id INT UNSIGNED NOT NULL, order_item_id INT UNSIGNED NOT NULL,
ingredient_id INT UNSIGNED NOT NULL, ingredient_id INT UNSIGNED NOT NULL,
@ -411,7 +417,7 @@ CREATE TABLE order_item_modifier (
-- 4.19 stock_movement — append-only audit log -- 4.19 stock_movement — append-only audit log
-- depends on ingredient, customer_order, user -- depends on ingredient, customer_order, user
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE stock_movement ( CREATE TABLE IF NOT EXISTS stock_movement (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
ingredient_id INT UNSIGNED NOT NULL, ingredient_id INT UNSIGNED NOT NULL,
movement_type ENUM('sale','cancellation','restock','inventory_correction') NOT NULL, movement_type ENUM('sale','cancellation','restock','inventory_correction') NOT NULL,
@ -437,7 +443,7 @@ CREATE TABLE stock_movement (
-- 4.20 audit_log — append-only sensitive-action log -- 4.20 audit_log — append-only sensitive-action log
-- depends on user, role -- depends on user, role
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
CREATE TABLE audit_log ( CREATE TABLE IF NOT EXISTS audit_log (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
actor_user_id INT UNSIGNED NULL, actor_user_id INT UNSIGNED NULL,
actor_role_id INT UNSIGNED NULL, actor_role_id INT UNSIGNED NULL,

View file

@ -16,7 +16,10 @@
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE pin_throttle ( -- Idempotence (defense en profondeur) : CREATE TABLE IF NOT EXISTS. La cle
-- unique, l'index et la FK sont inline dans le CREATE TABLE, donc non re-joues
-- quand la table preexiste. Re-jouer ce fichier ne modifie pas le schema.
CREATE TABLE IF NOT EXISTS pin_throttle (
id INT UNSIGNED NOT NULL AUTO_INCREMENT, id INT UNSIGNED NOT NULL AUTO_INCREMENT,
actor_user_id INT UNSIGNED NOT NULL, actor_user_id INT UNSIGNED NOT NULL,
failed_attempts SMALLINT UNSIGNED NOT NULL DEFAULT 0, failed_attempts SMALLINT UNSIGNED NOT NULL DEFAULT 0,

View file

@ -13,5 +13,21 @@
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE customer_order -- Idempotence : meme garde information_schema que 0006/0007 (re-jouable sans
ADD COLUMN service_tag VARCHAR(20) NULL AFTER service_mode; -- erreur). On verifie l'absence de la colonne `service_tag` avant l'ALTER ;
-- si elle existe deja, on execute un no-op (DO 0). Le schema resultant est
-- inchange : seul l'ajout de la colonne (si absente) est joue.
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'customer_order' AND column_name = 'service_tag'
);
SET @ddl := IF(
@col_exists = 0,
'ALTER TABLE customer_order
ADD COLUMN service_tag VARCHAR(20) NULL AFTER service_mode',
'DO 0'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View file

@ -14,10 +14,26 @@
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE ingredient -- Idempotence : meme garde information_schema que 0007 (re-jouable sans erreur).
-- Les trois colonnes sont ajoutees ensemble ; l'existence de la premiere
-- (`energy_kcal_100g`) suffit donc a court-circuiter le groupe. Si elle existe
-- deja, on execute un no-op (DO 0). Le schema resultant est inchange.
SET @col_exists := (
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'ingredient' AND column_name = 'energy_kcal_100g'
);
SET @ddl := IF(
@col_exists = 0,
'ALTER TABLE ingredient
ADD COLUMN energy_kcal_100g SMALLINT UNSIGNED NULL AFTER pack_label, ADD COLUMN energy_kcal_100g SMALLINT UNSIGNED NULL AFTER pack_label,
ADD COLUMN nutrition_source VARCHAR(120) NULL AFTER energy_kcal_100g, ADD COLUMN nutrition_source VARCHAR(120) NULL AFTER energy_kcal_100g,
ADD COLUMN nutrition_fetched_at DATETIME NULL AFTER nutrition_source; ADD COLUMN nutrition_fetched_at DATETIME NULL AFTER nutrition_source',
'DO 0'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- energy_kcal_100g : apport energetique pour 100 g (SMALLINT UNSIGNED suffit ; les -- energy_kcal_100g : apport energetique pour 100 g (SMALLINT UNSIGNED suffit ; les
-- valeurs reelles restent < 1000). nutrition_source : provenance ("OpenFoodFacts"). -- valeurs reelles restent < 1000). nutrition_source : provenance ("OpenFoodFacts").

View file

@ -1,11 +1,19 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# #
# Wakdo - seed runner. # Wakdo - seed runner (hote, via `docker exec`).
# #
# Applique les fichiers db/seeds/*.sql dans l'ordre lexicographique, de maniere # Applique les fichiers db/seeds/*.sql dans l'ordre lexicographique, de maniere
# idempotente : une table seed_history enregistre les fichiers deja charges. # idempotente : la table seeds_applied enregistre les fichiers deja charges.
# Les seeds doivent etre joues APRES les migrations (les tables doivent exister). # Les seeds doivent etre joues APRES les migrations (les tables doivent exister).
# #
# Contrepartie hote de db/migrate.sh : meme role que la phase seed du service de
# boot wakdo-migrate (db/migrate-container.sh), mais lance manuellement depuis
# l'hote. Le suivi DOIT utiliser la MEME table que le runner conteneur
# (seeds_applied) pour que les deux interoperent : rejouer l'un apres l'autre ne
# replaye RIEN. Auparavant ce script suivait une table distincte (seed_history),
# ce qui lui faisait re-jouer des seeds deja charges par wakdo-migrate (INSERT
# bruts -> echec sur contrainte UNIQUE).
#
# Cible : le service docker-compose `wakdo-db`. Identifiants lus dans .env. # Cible : le service docker-compose `wakdo-db`. Identifiants lus dans .env.
# #
# Usage : # Usage :
@ -34,7 +42,9 @@ if [ ! -d "$SEEDS_DIR" ]; then
exit 0 exit 0
fi fi
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS seed_history ( # Meme schema de suivi que db/migrate-container.sh (seeds_applied) : nom de table
# et colonnes identiques, pour que les deux runners partagent le meme journal.
db "$DB_NAME" -e "CREATE TABLE IF NOT EXISTS seeds_applied (
filename VARCHAR(255) NOT NULL PRIMARY KEY, filename VARCHAR(255) NOT NULL PRIMARY KEY,
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;" ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
@ -47,7 +57,7 @@ if [ "${1:-}" = "--status" ]; then
echo "[seed] etat des seeds (base $DB_NAME) :" echo "[seed] etat des seeds (base $DB_NAME) :"
for f in "${files[@]}"; do for f in "${files[@]}"; do
base="$(basename "$f")" base="$(basename "$f")"
n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seed_history WHERE filename='$base';")" n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seeds_applied WHERE filename='$base';")"
[ "$n" = "0" ] && echo " PENDING $base" || echo " loaded $base" [ "$n" = "0" ] && echo " PENDING $base" || echo " loaded $base"
done done
exit 0 exit 0
@ -56,11 +66,11 @@ fi
loaded=0 loaded=0
for f in "${files[@]}"; do for f in "${files[@]}"; do
base="$(basename "$f")" base="$(basename "$f")"
n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seed_history WHERE filename='$base';")" n="$(db "$DB_NAME" -N -s -e "SELECT COUNT(*) FROM seeds_applied WHERE filename='$base';")"
if [ "$n" = "0" ]; then if [ "$n" = "0" ]; then
echo "[seed] chargement de $base ..." echo "[seed] chargement de $base ..."
db "$DB_NAME" < "$f" db "$DB_NAME" < "$f"
db "$DB_NAME" -e "INSERT INTO seed_history (filename) VALUES ('$base');" db "$DB_NAME" -e "INSERT INTO seeds_applied (filename) VALUES ('$base');"
loaded=$((loaded + 1)) loaded=$((loaded + 1))
else else
echo "[seed] $base deja charge, ignore" echo "[seed] $base deja charge, ignore"