Skip to content

Commit 0dd1578

Browse files
committed
refactor: PostgreSQL data base full update + add tbls
1 parent f537fcd commit 0dd1578

172 files changed

Lines changed: 16651 additions & 4012 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

marius/sql/cmd.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Commandes d'installation sur Ubuntu
2+
3+
```sql
4+
# DDL, initialisation de la base de données
5+
# À lancer depuis la racine du dossier 'db'
6+
sudo -u postgres psql -p 5433 -d postgres -f master_init.sql
7+
```
8+
9+
```sql
10+
# On injecte des données de test dans la base 'marius' déjà créée
11+
sudo -u postgres psql -p 5433 -d marius -f master_schema_dml.pgsql
12+
```
13+
14+
```sql
15+
# Recalibrage des stats PG
16+
# PostgreSQL a besoin de "compter" les lignes physiquement pour mettre à jour ses statistiques.
17+
sudo -u postgres psql -p 5433 -d marius -c "ANALYZE;"
18+
```
19+
20+
```sql
21+
# Audit de sécurité
22+
# Lecture de l'état de santé DOD/ECS
23+
sudo -u postgres psql -p 5433 -d marius -c "SELECT * FROM meta.v_master_health_audit;"
24+
```

marius/sql/db/.tbls.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Format standard : postgres://USER:PASSWORD@HOST:PORT/DBNAME?sslmode=disable
2+
dsn: postgres://postgres:marius@localhost:5433/marius?sslmode=disable
3+
docPath: doc
4+
exclude:
5+
- pg_.*
6+
- information_schema.*
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-- ==============================================================================
2+
-- 00_infra/01_bootstrap.sql
3+
-- Architecture ECS/DOD · Projet Marius · PostgreSQL 18
4+
-- Exécution : depuis la base postgres (via master_init.sql)
5+
-- Rôle : réinitialisation complète (DROP DATABASE + rôles + re-création)
6+
-- ==============================================================================
7+
8+
DROP DATABASE IF EXISTS marius;
9+
10+
-- marius_admin doit être nettoyé avant marius_user (héritage GRANT marius_user TO marius_admin).
11+
-- Sans cet ordre, DROP USER marius_user échoue si le GRANT existe encore.
12+
-- Ces trois commandes échouent silencieusement si marius_admin n'existe pas encore (premier déploiement).
13+
REASSIGN OWNED BY marius_admin TO postgres;
14+
DROP OWNED BY marius_admin;
15+
DROP ROLE IF EXISTS marius_admin;
16+
17+
REASSIGN OWNED BY marius_user TO postgres;
18+
DROP OWNED BY marius_user;
19+
DROP USER IF EXISTS marius_user;
20+
21+
CREATE USER marius_user WITH ENCRYPTED PASSWORD 'root';
22+
CREATE DATABASE marius OWNER marius_user;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
-- ==============================================================================
2+
-- 00_infra/02_extensions.sql
3+
-- Architecture ECS/DOD · Projet Marius · PostgreSQL 18
4+
-- Contenu : extensions PostgreSQL + fonctions utilitaires cross-schéma (public)
5+
-- Ordre : doit précéder toute table référençant ces extensions ou fonctions
6+
-- ==============================================================================
7+
8+
-- ==============================================================================
9+
-- EXTENSIONS
10+
-- ==============================================================================
11+
12+
CREATE EXTENSION unaccent; -- normalisation des accents (recherche texte)
13+
CREATE EXTENSION ltree; -- chemins matérialisés (tags, commentaires)
14+
CREATE EXTENSION pg_trgm; -- index trigrammes (recherche partielle sur noms)
15+
CREATE EXTENSION postgis; -- types et index géospatiaux (geo.place_core)
16+
17+
18+
-- ==============================================================================
19+
-- WRAPPER IMMUTABLE UNACCENT
20+
-- ==============================================================================
21+
-- Wrapper IMMUTABLE requis pour l'utilisation de unaccent() dans les index.
22+
-- unaccent() n'est pas déclarée IMMUTABLE dans PostgreSQL (dépendance de dictionnaire).
23+
-- Ce wrapper délègue à unaccent() et hérite de son comportement fonctionnel, mais
24+
-- permet au planner de traiter l'expression comme stable entre les lignes — prérequis
25+
-- pour toute expression d'index. Tout changement de dictionnaire unaccent nécessite
26+
-- un REINDEX sur les index qui l'utilisent (org_identity_name_trgm, content_identity_headline_trgm).
27+
CREATE FUNCTION public.immutable_unaccent(text)
28+
RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$
29+
SELECT public.unaccent($1);
30+
$$;
31+
32+
33+
-- ==============================================================================
34+
-- DÉDUPLICATION DE SLUGS (utilitaire cross-schéma)
35+
-- ==============================================================================
36+
-- Fonctionne sur n'importe quelle table via TG_TABLE_SCHEMA / TG_TABLE_NAME.
37+
-- Ignore la ligne courante (PK <> valeur courante) pour les UPDATE.
38+
--
39+
-- COMPORTEMENT SOUS CONCURRENCE
40+
-- La boucle SELECT EXISTS + incrément fonctionne correctement en session unique.
41+
-- Sous forte concurrence (deux transactions qui génèrent le même slug simultanément),
42+
-- la contrainte UNIQUE est le vrai garde-fou : elle rejettera l'une des deux
43+
-- insertions avec une erreur 23505 (unique_violation). Ce n'est pas un état
44+
-- corrompu — l'erreur est propre et attrapable côté applicatif.
45+
-- Le pattern "déduplication optimiste + UNIQUE comme filet" est acceptable pour
46+
-- les slugs (générés depuis un titre, collisions rares). Pour un système à très
47+
-- haute concurrence sur les titres (ex: importation de masse), préférer une
48+
-- séquence applicationnelle avec retry explicite.
49+
CREATE FUNCTION public.fn_slug_deduplicate()
50+
RETURNS TRIGGER LANGUAGE plpgsql AS $$
51+
DECLARE
52+
v_slug TEXT := NEW.slug;
53+
v_exists BOOLEAN;
54+
v_counter INT := 0;
55+
v_pk_col TEXT;
56+
v_pk_val INT;
57+
BEGIN
58+
-- Détection de la colonne PK par convention de nommage
59+
v_pk_col := CASE TG_TABLE_NAME
60+
WHEN 'account_core' THEN 'entity_id'
61+
WHEN 'identity' THEN 'document_id'
62+
ELSE 'id'
63+
END;
64+
65+
EXECUTE format('SELECT ($1).%I', v_pk_col) INTO v_pk_val USING NEW;
66+
67+
LOOP
68+
EXECUTE format(
69+
'SELECT EXISTS(SELECT 1 FROM %I.%I WHERE slug = $1 AND %I <> $2)',
70+
TG_TABLE_SCHEMA, TG_TABLE_NAME, v_pk_col
71+
) INTO v_exists USING v_slug, COALESCE(v_pk_val, -1);
72+
EXIT WHEN NOT v_exists;
73+
v_counter := v_counter + 1;
74+
v_slug := NEW.slug || '-' || v_counter;
75+
END LOOP;
76+
77+
NEW.slug := v_slug;
78+
RETURN NEW;
79+
END;
80+
$$;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- ==============================================================================
2+
-- 00_infra/03_schemas.sql
3+
-- Architecture ECS/DOD · Projet Marius · PostgreSQL 18
4+
-- Contenu : création de tous les schémas applicatifs + schéma méta AOT
5+
-- Ordre : doit précéder toute création de table ou de fonction qualifiée
6+
-- ==============================================================================
7+
8+
CREATE SCHEMA meta; -- registre AOT + sentinelles d'audit (chargé en 01_meta/)
9+
CREATE SCHEMA identity; -- acteurs, authentification, permissions
10+
CREATE SCHEMA geo; -- lieux, adresses postales, coordonnées spatiales
11+
CREATE SCHEMA org; -- organisations, hiérarchies
12+
CREATE SCHEMA commerce; -- produits, transactions, paiements
13+
CREATE SCHEMA content; -- documents, médias, taxonomie, commentaires
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
-- ==============================================================================
2+
-- 01_meta/01_tables.sql
3+
-- Architecture ECS/DOD · Projet Marius · PostgreSQL 18
4+
-- Contenu : meta.containment_intent (registre d'intention AOT) + migrations
5+
-- Source : meta_registry.sql v2.2
6+
-- ==============================================================================
7+
8+
-- ==============================================================================
9+
-- REGISTRE D'INTENTION (Source of Truth architecturale)
10+
-- ==============================================================================
11+
-- Chaque ligne déclare les invariants d'un composant ECS. L'outil compare
12+
-- cette intention à la réalité extraite de pg_catalog.
13+
--
14+
-- component_id TEXT (pas regclass) :
15+
-- Stocke le nom qualifié ('schema.table'). to_regclass() est utilisé dans
16+
-- les vues pour la résolution — retourne NULL si la table n'existe pas encore
17+
-- au lieu de lever une erreur. Permet la pré-déclaration d'un composant avant
18+
-- sa création physique (workflow migration : intention déclarée → DDL appliqué
19+
-- → alerte component_not_found_alert passe de TRUE à FALSE).
20+
-- Contrepartie : un renommage de table n'est pas suivi automatiquement
21+
-- (contrairement à regclass qui stocke l'OID). Mise à jour manuelle requise.
22+
--
23+
-- mutation_procedures TEXT[] (pas regprocedure) :
24+
-- Plusieurs procédures peuvent écrire le même composant (ex: identity.auth
25+
-- est écrit par create_account, record_login ET anonymize_person). Le modèle
26+
-- 1:1 est architecturalement incorrect pour un système ECS. Format attendu :
27+
-- signature complète avec types d'arguments pour to_regprocedure() :
28+
-- 'identity.record_login(integer)'.
29+
--
30+
-- immutable_keys name[] :
31+
-- Colonnes scellées post-INSERT (FK spine, clés de tri BRIN...). Métadonnée
32+
-- documentaire — les triggers d'immuabilité correspondants sont vérifiés
33+
-- dans les tests pgTAP (11_meta_audit.sql).
34+
--
35+
-- exempt_bloat_check BOOLEAN :
36+
-- Neutralise la contribution bloat dans le scoring de v_master_health_audit.
37+
-- Réservé aux tables de configuration structurelle (cardinalité fixe, mutations
38+
-- REVOKE'd en production). N'affecte pas v_performance_sentinel ni
39+
-- density_drift_alert — la réalité physique reste visible pour diagnostic.
40+
--
41+
-- naive_density_bytes SMALLINT NULL (v2.2) :
42+
-- Taille du tuple padded si les colonnes étaient dans leur ordre naturel pré-DOD
43+
-- (non optimisé), produite par f_generate_dod_template sur la liste originale.
44+
-- NULL = non renseigné (métrique optionnelle, aucun effet sur les alertes).
45+
-- Le ratio dod_efficiency_ratio = naive / intent est exposé dans
46+
-- v_extended_containment_security_matrix comme KPI architectural.
47+
48+
CREATE TABLE IF NOT EXISTS meta.containment_intent (
49+
component_id TEXT NOT NULL PRIMARY KEY,
50+
intent_density_bytes SMALLINT NOT NULL,
51+
rls_guard_bitmask INT NULL,
52+
mutation_procedures TEXT[] NULL,
53+
immutable_keys name[] NULL,
54+
55+
CONSTRAINT intent_density_positive CHECK (intent_density_bytes > 0),
56+
CONSTRAINT component_id_format CHECK (component_id ~ '^[a-z_]+\.[a-z_0-9]+$')
57+
);
58+
59+
-- ── Migrations idempotentes ────────────────────────────────────────────────────
60+
-- Chaque colonne ajoutée après la version initiale est déclarée via ADD COLUMN IF
61+
-- NOT EXISTS. Ce bloc est sans effet sur une base fraîche (les colonnes sont déjà
62+
-- présentes via CREATE TABLE IF NOT EXISTS qui aurait créé la table complète) et
63+
-- applique uniquement les colonnes manquantes sur une base existante à une version
64+
-- antérieure.
65+
66+
-- v2.1 — exempt_bloat_check
67+
ALTER TABLE meta.containment_intent
68+
ADD COLUMN IF NOT EXISTS exempt_bloat_check BOOLEAN NOT NULL DEFAULT false;
69+
70+
-- v2.2 — naive_density_bytes + contraintes associées
71+
ALTER TABLE meta.containment_intent
72+
ADD COLUMN IF NOT EXISTS naive_density_bytes SMALLINT NULL;
73+
74+
-- Contraintes ajoutées en v2.2 — idempotentes via DO/EXCEPTION.
75+
-- pg_constraint n'a pas de IF NOT EXISTS ; on teste l'existence avant d'ajouter.
76+
DO $$
77+
BEGIN
78+
IF NOT EXISTS (
79+
SELECT 1 FROM pg_constraint
80+
WHERE conname = 'naive_density_positive'
81+
AND conrelid = 'meta.containment_intent'::regclass
82+
) THEN
83+
ALTER TABLE meta.containment_intent
84+
ADD CONSTRAINT naive_density_positive
85+
CHECK (naive_density_bytes IS NULL OR naive_density_bytes > 0);
86+
END IF;
87+
88+
IF NOT EXISTS (
89+
SELECT 1 FROM pg_constraint
90+
WHERE conname = 'naive_gte_intent'
91+
AND conrelid = 'meta.containment_intent'::regclass
92+
) THEN
93+
ALTER TABLE meta.containment_intent
94+
ADD CONSTRAINT naive_gte_intent
95+
CHECK (naive_density_bytes IS NULL OR naive_density_bytes >= intent_density_bytes);
96+
END IF;
97+
END;
98+
$$;

0 commit comments

Comments
 (0)