from ..connection import connect from ..constants import FIELD_TYPES from ..quote_ident import quote_ident from ..slugify import slugify from .get_definition import get_definition def add_field_to_definition(slug, definition_id, field): """CRUD — Update d'une définition : ajoute un champ à un objet déjà créé. Exécute un vrai ALTER TABLE ... ADD COLUMN sur la table SQL existante (les lignes déjà enregistrées reçoivent NULL pour ce nouveau champ, comportement standard d'un ALTER TABLE).""" definition = get_definition(slug, definition_id) conn = connect(slug) fname = slugify(field["name"]).replace("-", "_") ftype = field["type"] required = 1 if field.get("required") else 0 relation_definition_id = None position = (max((f["position"] for f in definition["fields"]), default=-1)) + 1 if ftype == "relation": related = get_definition(slug, int(field["relation_definition_id"])) col = f"{fname}_id" # ALTER TABLE ADD COLUMN de SQLite n'accepte pas de contrainte # REFERENCES portant sur une colonne ajoutée après coup avec la # même simplicité qu'à la création : on ajoute la colonne simple — # c'est la table _fields qui reste la source de vérité utilisée par # le moteur pour savoir que cette colonne est une relation. conn.execute(f"ALTER TABLE {definition['table_name']} ADD COLUMN {quote_ident(col)} INTEGER") relation_definition_id = related["id"] else: sql_type = FIELD_TYPES[ftype]["sql"] conn.execute(f"ALTER TABLE {definition['table_name']} ADD COLUMN {quote_ident(fname)} {sql_type}") min_value = field.get("min_value") if ftype in ("nombre_entier", "nombre_decimal") else None max_value = field.get("max_value") if ftype in ("nombre_entier", "nombre_decimal") else None conn.execute( """INSERT INTO _fields (definition_id, name, type, relation_definition_id, required, position, min_value, max_value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", (definition_id, field["name"], ftype, relation_definition_id, required, position, min_value, max_value), ) conn.commit() conn.close()