Procédure publique · ORM_CSHX2 · Administration BDD

ORM_ResetSequence

Recalage de la séquence d'auto-incrément d'une clé primaire sur MAX(PK)+1. Indispensable après un import de données avec IDs explicites — sans recalage, le prochain INSERT en auto-incrément génère un conflit de clé primaire. PostgreSQL uniquement à ce jour.

PUBLIQUE ADMINISTRATION BDD PostgreSQL uniquement
01

📋 Description

ORM_ResetSequence resynchronise la séquence d'auto-incrément d'une colonne clé primaire sur la valeur MAX(PK) + 1. Cette opération est nécessaire après tout chargement de données qui contourne le mécanisme d'auto-incrément du moteur — typiquement un import avec IDs explicites.

Sans ce recalage, le moteur SQL conserve son compteur interne à la valeur précédant l'import. Le prochain INSERT sans ID explicite générera donc une valeur inférieure ou égale à celles déjà présentes en base, et provoquera une erreur de conflit de clé primaire.

🎯 Quand utiliser cette procédure

1. Après un import de données avec IDs explicites. Cas le plus fréquent : reprise depuis une autre base, restauration partielle, migration entre environnements. Les IDs ont été insérés tels quels mais le compteur interne de la séquence n'a pas été mis à jour automatiquement.

2. Après une copie de table par INSERT INTO ... SELECT qui préserve les valeurs originales de la clé primaire — même problématique que pour un import depuis l'extérieur.

3. Après une opération de fusion ou de réorganisation qui a inséré des enregistrements avec des IDs supérieurs à la valeur courante de la séquence.

⚠️ PostgreSQL uniquement à ce jour

L'implémentation actuelle ne couvre que PostgreSQL. Les providers MySQL et MariaDB (qui utilisent ALTER TABLE ... AUTO_INCREMENT au lieu de ALTER SEQUENCE) ne sont pas encore supportés. Un appel avec un autre provider provoque actuellement un arrêt en mode test ou un comportement non spécifié en production. Le support multi-provider est prévu — voir le journal d'évolution du framework.

ℹ️ Pas de verrouillage de la table

L'instruction ALTER SEQUENCE ... RESTART de PostgreSQL est non bloquante : elle ne pose pas de verrou exclusif sur la table associée. La procédure peut donc être appelée en concurrence avec un trafic applicatif. Cela dit, en pratique on l'invoque typiquement après un import en mode maintenance, donc le point a peu d'impact opérationnel.

02

🔑 Signature

Déclaration
PROCÉDURE ORM_ResetSequence(
  LOCAL sTableSQL est une chaîne,
  LOCAL sCléPrimaire est une chaîne
) : (booléen, entier, chaîne)
ÉlémentValeur
VisibilitéPUBLIQUE

Paramètres

ParamètreTypeRôle
sTableSQLchaîneNom de la table SQL dont la séquence d'auto-incrément doit être recalée.
sCléPrimairechaîneNom de la colonne clé primaire auto-incrémentée associée à la séquence.

Valeur de retour

ÉlémentTypeDescription
bProcessingbooléenVrai si le recalage a réussi, Faux en cas d'échec.
nErrorCodeentierCode d'erreur négatif en cas d'échec, 0 sinon. Voir §05.
sErrorMessagechaîneMessage d'erreur lisible en cas d'échec, vide sinon.
03

🛡️ Étapes du recalage

Le recalage s'effectue en trois étapes successives. Chaque étape peut échouer indépendamment et déclenche un code d'erreur dédié pour faciliter le diagnostic.

PostgreSQL — 3 étapes

ÉtapeOpérationEffet
1. Lecture du MAX(PK)SELECT MAX(<clé>) FROM <table>Récupère la plus grande valeur de clé primaire actuellement présente dans la table.
2. Identification de la séquenceRequête sur les catalogues système PostgreSQLLocalise le nom de la séquence PostgreSQL liée à la colonne clé primaire (chaque colonne SERIAL/BIGSERIAL/IDENTITY est associée à une séquence dédiée par le moteur).
3. RecalageALTER SEQUENCE "<séquence>" RESTART <max+1>Repositionne le compteur interne de la séquence sur MAX(PK) + 1. Le prochain INSERT en auto-incrément génèrera donc une valeur strictement supérieure à toutes celles déjà présentes.
ℹ️ Cas de la table vide

Si la table est vide, MAX(<clé>) renvoie NULL. La séquence est alors recalée à NULL + 1 = 1 — donc le prochain INSERT obtiendra l'ID 1. Ce comportement convient pour réinitialiser une table après un TRUNCATE, par exemple.

🛡️ Pré-requis architectural

La connexion ORM courante doit pointer sur la base de données contenant la table cible. Les catalogues système PostgreSQL consultés à l'étape 2 sont scopés à la base courante : impossible d'identifier une séquence d'une autre base via la connexion en cours.

Le rôle courant doit avoir le droit ALTER sur la séquence cible. Typiquement, c'est le rôle propriétaire de la séquence (créateur de la table) ou un superutilisateur. Un compte applicatif standard (créé par ORM_CreateUser avec ses droits DML uniquement) ne peut pas appeler cette procédure.

MySQL / MariaDB — non implémenté

Le support MySQL/MariaDB n'est pas implémenté à ce jour. L'équivalent fonctionnel serait ALTER TABLE <table> AUTO_INCREMENT = <max+1>, mais cette branche n'est pas active dans la version actuelle du framework. Un appel sur ces providers ne donnera pas le résultat attendu.

04

🧭 Cas typique d'utilisation

Pour comprendre concrètement pourquoi ce recalage est nécessaire, voici le scénario le plus fréquent : un import de données depuis une source externe.

Sans recalage — le scénario qui échoue

ÉtapeActionÉtat de la séquence
1Table articles vide. Compteur de séquence à 1.1
2Import en masse : INSERT INTO articles (ID, ...) VALUES (1, ...), (2, ...), ..., (1000, ...)1 (inchangé — le compteur ne suit pas les IDs explicites)
3L'application crée un nouvel article : INSERT INTO articles (DESIGNATION, ...) VALUES (...) — sans ID explicite, le moteur prend 1 dans la séquence.Erreur : conflit de clé primaire (ID 1 déjà utilisé)

Avec recalage — le scénario qui réussit

ÉtapeActionÉtat de la séquence
1Table articles vide. Compteur à 1.1
2Import en masse comme précédemment.1
3ORM_ResetSequence("articles", "ID") → recale la séquence sur 1001.1001
4L'application crée un nouvel article sans ID explicite.✅ Le moteur génère l'ID 1001 — pas de conflit.
05

⚠️ Gestion des erreurs

Chaque étape du recalage peut échouer indépendamment et déclenche un code d'erreur spécifique pour faciliter le diagnostic.

ConstanteÉtape concernée
ERR_ORM_SEQ_SELECT_MAX_PKÉchec de l'étape 1 (lecture de MAX(clé)). Causes possibles : table inexistante, colonne inexistante, droits insuffisants en SELECT.
ERR_ORM_SEQ_SELECT_PG_CLASSÉchec de l'étape 2 (identification de la séquence dans les catalogues système PostgreSQL). Cause typique : droits insuffisants pour interroger le catalogue système.
ERR_ORM_SEQ_INTROUVABLEL'étape 2 a réussi mais aucune séquence n'est associée à la combinaison (table, colonne) indiquée. La colonne n'est probablement pas en auto-incrément (ce n'est ni un SERIAL, ni un BIGSERIAL, ni un IDENTITY).
ERR_ORM_SEQ_ALTERÉchec de l'étape 3 (ALTER SEQUENCE RESTART). Cause typique : droits ALTER insuffisants sur la séquence.
-99999Exception non prévue. Consulter sErrorMessage pour le détail (typiquement remonté par le moteur SQL).
⚠️ Diagnostic ERR_ORM_SEQ_INTROUVABLE

Ce code d'erreur signale que la colonne désignée n'a pas de séquence associée côté PostgreSQL. Avant d'incriminer la procédure, vérifier que :

• La colonne est bien définie comme SERIAL, BIGSERIAL ou IDENTITY dans le schéma physique
• Les paramètres sTableSQL et sCléPrimaire sont écrits avec la bonne casse (PostgreSQL est case-sensitive sur les identifiants encadrés par des guillemets)
• La table appartient bien au schéma de la connexion courante

06

💡 Exemples

Mode 1 — recalage après import nominal

Cas d'usage : après un import en masse depuis un fichier CSV ou une base externe, on remet la séquence en cohérence avec les IDs présents.

// ── Import achevé : 1 000 articles insérés avec IDs explicites ── (bProcessing, nErrorCode, sErrorMessage) = ORM_ResetSequence(
  "articles",   "ID_ARTICLE" ) SI bProcessing ALORS Info("Séquence recalée — l'application peut reprendre normalement") SINON Erreur("Échec du recalage : " + sErrorMessage) FIN

Mode 2 — recalage en boucle après une migration multi-tables

Cas d'usage : restauration ou migration qui touche plusieurs tables — on parcourt la liste pour recaler chaque séquence.

// ── Liste des tables migrées avec leur clé primaire ───────────── tabTables est un tableau de chaînes TableauAjoute(tabTables, "articles|ID_ARTICLE") TableauAjoute(tabTables, "clients|ID_CLIENT") TableauAjoute(tabTables, "commandes|ID_COMMANDE") // ── Recalage de chaque séquence ───────────────────────────────── POUR TOUT sLigne DE tabTables sTable est une chaîne = ExtraitChaîne(sLigne, 1, "|") sCle est une chaîne = ExtraitChaîne(sLigne, 2, "|") (bProcessing, nErrorCode, sErrorMessage) = ORM_ResetSequence(sTable, sCle) SI bProcessing = Faux ALORS Trace("Échec recalage " + sTable + " : " + sErrorMessage) // Décider de continuer ou interrompre selon politique de migration FIN FIN

Mode 3 — diagnostic d'une erreur typique

Cas d'usage : on a appelé la procédure sur une colonne qui se trouve ne pas être en auto-incrément (oubli ou erreur de schéma).

(bProcessing, nErrorCode, sErrorMessage) = ORM_ResetSequence("clients", "REFERENCE") // → REFERENCE est de type chaîne, pas un auto-incrément SI bProcessing = Faux ALORS SELON nErrorCode CAS ERR_ORM_SEQ_INTROUVABLE // La colonne n'a pas de séquence — vérifier le schéma physique Erreur("Aucune séquence trouvée pour clients.REFERENCE." + RC + "Vérifier que la colonne est bien en auto-incrément (SERIAL, BIGSERIAL ou IDENTITY).") CAS ERR_ORM_SEQ_SELECT_MAX_PK Erreur("Impossible de lire MAX sur la colonne. Table ou colonne inexistante ?") CAS ERR_ORM_SEQ_ALTER Erreur("Le rôle courant n'a pas le droit ALTER sur la séquence.") AUTRE CAS Erreur("Erreur inattendue : " + sErrorMessage) FIN FIN

Mode 4 — recalage après ORM_TruncateTable

Cas d'usage : nettoyage complet d'une table puis ré-import. Le TRUNCATE peut, selon les options, conserver ou non la séquence — un recalage explicite garantit le comportement attendu.

// ── 1. Vidage complet de la table ─────────────────────────────── (bProcessing, nErrorCode, sErrorMessage) = ORM_TruncateTable("articles") SI bProcessing ALORS // ── 2. Ré-import des articles depuis la source de référence ─ // (insertion avec IDs explicites) // ... // ── 3. Recalage explicite de la séquence ──────────────────── (bProcessing, nErrorCode, sErrorMessage) = ORM_ResetSequence("articles", "ID_ARTICLE") SI bProcessing ALORS Info("Réinitialisation de la table articles terminée") FIN FIN