diff --git a/data/package.sql b/data/package.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4044d99e66dcf248cb0c76e473e5dc1ab92eb14f
--- /dev/null
+++ b/data/package.sql
@@ -0,0 +1,356 @@
+create or replace PACKAGE "UNICAEN_TBL" AS
+
+  TYPE t_params IS RECORD (
+    c1 VARCHAR2(30), v1 VARCHAR2(80),
+    c2 VARCHAR2(30), v2 VARCHAR2(80),
+    c3 VARCHAR2(30), v3 VARCHAR2(80),
+    c4 VARCHAR2(30), v4 VARCHAR2(80),
+    c5 VARCHAR2(30), v5 VARCHAR2(80),
+    sqlcond CLOB
+    );
+
+  ACTIV_TRIGGERS BOOLEAN DEFAULT TRUE;
+  ACTIV_CALCULS  BOOLEAN DEFAULT TRUE;
+  CALCUL_PROC_PARAMS t_params;
+
+  FUNCTION MAKE_PARAMS(
+    c1 VARCHAR2 DEFAULT NULL, v1 VARCHAR2 DEFAULT NULL,
+    c2 VARCHAR2 DEFAULT NULL, v2 VARCHAR2 DEFAULT NULL,
+    c3 VARCHAR2 DEFAULT NULL, v3 VARCHAR2 DEFAULT NULL,
+    c4 VARCHAR2 DEFAULT NULL, v4 VARCHAR2 DEFAULT NULL,
+    c5 VARCHAR2 DEFAULT NULL, v5 VARCHAR2 DEFAULT NULL,
+    sqlcond CLOB DEFAULT NULL
+  ) RETURN t_params;
+
+  FUNCTION PARAMS_FROM_DEMS( TBL_NAME VARCHAR2 ) RETURN t_params;
+  FUNCTION PARAMS_TO_CONDS ( PARAMS UNICAEN_TBL.T_PARAMS, alias VARCHAR2 DEFAULT NULL ) RETURN CLOB;
+
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2 );
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2, CONDS CLOB );
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2, PARAMS t_params );
+
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2 );
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2, CONDS CLOB );
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2, PARAMS t_params );
+
+  PROCEDURE ANNULER_DEMANDES;
+  PROCEDURE ANNULER_DEMANDES( TBL_NAME VARCHAR2 );
+  PROCEDURE CALCULER_DEMANDES;
+
+  -- AUTOMATIC GENERATION --
+
+  -- END OF AUTOMATIC GENERATION --
+
+END UNICAEN_TBL;
+/
+
+
+create or replace PACKAGE BODY "UNICAEN_TBL" AS
+
+  FUNCTION MAKE_PARAMS(
+    c1 VARCHAR2 DEFAULT NULL, v1 VARCHAR2 DEFAULT NULL,
+    c2 VARCHAR2 DEFAULT NULL, v2 VARCHAR2 DEFAULT NULL,
+    c3 VARCHAR2 DEFAULT NULL, v3 VARCHAR2 DEFAULT NULL,
+    c4 VARCHAR2 DEFAULT NULL, v4 VARCHAR2 DEFAULT NULL,
+    c5 VARCHAR2 DEFAULT NULL, v5 VARCHAR2 DEFAULT NULL,
+    sqlcond CLOB DEFAULT NULL
+  ) RETURN t_params IS
+    params t_params;
+  BEGIN
+    IF c1 IS NOT NULL THEN
+      params.c1 := c1;
+      params.v1 := v1;
+    END IF;
+    IF c2 IS NOT NULL THEN
+      params.c2 := c2;
+      params.v2 := v2;
+    END IF;
+    IF c3 IS NOT NULL THEN
+      params.c3 := c3;
+      params.v3 := v3;
+    END IF;
+    IF c4 IS NOT NULL THEN
+      params.c4 := c4;
+      params.v4 := v4;
+    END IF;
+    IF c5 IS NOT NULL THEN
+      params.c5 := c5;
+      params.v5 := v5;
+    END IF;
+    params.sqlcond := sqlcond;
+
+    RETURN params;
+  END;
+
+
+
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2 ) IS
+    p t_params;
+  BEGIN
+    DEMANDE_CALCUL( tbl_name, p );
+  END;
+
+
+
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2, CONDS CLOB ) IS
+    p t_params;
+  BEGIN
+    p.sqlcond := CONDS;
+    DEMANDE_CALCUL( tbl_name, p );
+  END;
+
+
+
+  PROCEDURE DEMANDE_CALCUL( TBL_NAME VARCHAR2, PARAMS t_params ) IS
+  BEGIN
+    INSERT INTO tbl_dems (
+      ID,
+      TBL_NAME,
+      c1, v1,
+      c2, v2,
+      c3, v3,
+      c4, v4,
+      c5, v5,
+      sqlcond
+    ) VALUES (
+               TBL_DEMS_ID_SEQ.NEXTVAL,
+               TBL_NAME,
+               PARAMS.c1, PARAMS.v1,
+               PARAMS.c2, PARAMS.v2,
+               PARAMS.c3, PARAMS.v3,
+               PARAMS.c4, PARAMS.v4,
+               PARAMS.c5, PARAMS.v5,
+               PARAMS.sqlcond
+             );
+  END;
+
+
+
+  FUNCTION PARAMS_FROM_DEMS( TBL_NAME VARCHAR2 ) RETURN t_params IS
+    res t_params;
+    conds CLOB := '';
+    cond CLOB;
+  BEGIN
+    FOR d IN (
+      SELECT *
+      FROM   tbl_dems
+      WHERE  tbl_name = PARAMS_FROM_DEMS.TBL_NAME
+      )
+      LOOP
+
+        cond := '';
+
+        IF d.c1 IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          IF d.v1 IS NULL THEN
+            cond := cond || d.c1 || ' IS NULL';
+          ELSE
+            cond := cond || d.c1 || '=' || d.v1;
+          END IF;
+        END IF;
+
+        IF d.c2 IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          IF d.v2 IS NULL THEN
+            cond := cond || d.c2 || ' IS NULL';
+          ELSE
+            cond := cond || d.c2 || '=' || d.v2;
+          END IF;
+        END IF;
+
+        IF d.c3 IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          IF d.v3 IS NULL THEN
+            cond := cond || d.c3 || ' IS NULL';
+          ELSE
+            cond := cond || d.c3 || '=' || d.v3;
+          END IF;
+        END IF;
+
+        IF d.c4 IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          IF d.v4 IS NULL THEN
+            cond := cond || d.c4 || ' IS NULL';
+          ELSE
+            cond := cond || d.c4 || '=' || d.v4;
+          END IF;
+        END IF;
+
+        IF d.c5 IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          IF d.v5 IS NULL THEN
+            cond := cond || d.c5 || ' IS NULL';
+          ELSE
+            cond := cond || d.c5 || '=' || d.v5;
+          END IF;
+        END IF;
+
+        IF d.sqlcond IS NOT NULL THEN
+          IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+          cond := cond || '(' || d.sqlcond || ')';
+        END IF;
+
+        IF conds IS NOT NULL THEN
+          conds := conds || ' OR ';
+        END IF;
+        conds := conds || '(' || cond || ')';
+      END LOOP;
+
+    res.sqlcond := conds;
+    DELETE FROM tbl_dems WHERE tbl_name = PARAMS_FROM_DEMS.TBL_NAME;
+    RETURN res;
+  END;
+
+
+
+  FUNCTION PARAMS_TO_CONDS ( PARAMS UNICAEN_TBL.T_PARAMS, alias VARCHAR2 DEFAULT NULL ) RETURN CLOB IS
+    cond CLOB;
+    a VARCHAR2(30);
+  BEGIN
+    IF alias IS NULL THEN
+      a := '';
+    ELSE
+      a := alias || '.';
+    END IF;
+    IF params.c1 IS NOT NULL THEN
+      IF params.v1 IS NULL THEN
+        cond := cond || a || params.c1 || ' IS NULL';
+      ELSE
+        cond := cond || a || params.c1 || '=' || params.v1;
+      END IF;
+    END IF;
+
+    IF params.c2 IS NOT NULL THEN
+      IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+      IF params.v2 IS NULL THEN
+        cond := cond || a || params.c2 || ' IS NULL';
+      ELSE
+        cond := cond || a || params.c2 || '=' || params.v2;
+      END IF;
+    END IF;
+
+    IF params.c3 IS NOT NULL THEN
+      IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+      IF params.v3 IS NULL THEN
+        cond := cond || a || params.c3 || ' IS NULL';
+      ELSE
+        cond := cond || a || params.c3 || '=' || params.v3;
+      END IF;
+    END IF;
+
+    IF params.c4 IS NOT NULL THEN
+      IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+      IF params.v4 IS NULL THEN
+        cond := cond || a || params.c4 || ' IS NULL';
+      ELSE
+        cond := cond || a || params.c4 || '=' || params.v4;
+      END IF;
+    END IF;
+
+    IF params.c5 IS NOT NULL THEN
+      IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+      IF params.v5 IS NULL THEN
+        cond := cond || a || params.c5 || ' IS NULL';
+      ELSE
+        cond := cond || a || params.c5 || '=' || params.v5;
+      END IF;
+    END IF;
+
+    IF params.sqlcond IS NOT NULL THEN
+      IF cond IS NOT NULL THEN cond := cond || ' AND '; END IF;
+      cond := cond || '(' || params.sqlcond || ')';
+    END IF;
+
+    IF cond IS NULL THEN cond := '1=1'; END IF;
+
+    RETURN cond;
+  END;
+
+
+
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2 ) IS
+    p t_params;
+  BEGIN
+    ANNULER_DEMANDES( TBL_NAME );
+    CALCULER(TBL_NAME, p);
+  END;
+
+
+
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2, CONDS CLOB ) IS
+    p t_params;
+  BEGIN
+    p.sqlcond := CONDS;
+    CALCULER(TBL_NAME, p);
+  END;
+
+
+
+  PROCEDURE CALCULER( TBL_NAME VARCHAR2, PARAMS t_params ) IS
+    calcul_proc varchar2(30);
+  BEGIN
+    IF NOT UNICAEN_TBL.ACTIV_CALCULS THEN RETURN; END IF;
+
+    SELECT custom_calcul_proc INTO calcul_proc FROM tbl WHERE tbl_name = CALCULER.TBL_NAME;
+
+    UNICAEN_TBL.CALCUL_PROC_PARAMS := PARAMS;
+    IF calcul_proc IS NOT NULL THEN
+      EXECUTE IMMEDIATE
+          'BEGIN ' || calcul_proc || '(UNICAEN_TBL.CALCUL_PROC_PARAMS); END;'
+      ;
+    ELSE
+      EXECUTE IMMEDIATE
+          'BEGIN UNICAEN_TBL.C_' || TBL_NAME || '(UNICAEN_TBL.CALCUL_PROC_PARAMS); END;'
+      ;
+    END IF;
+
+  END;
+
+
+
+  PROCEDURE ANNULER_DEMANDES IS
+  BEGIN
+    DELETE FROM tbl_dems;
+  END;
+
+
+
+  PROCEDURE ANNULER_DEMANDES( TBL_NAME VARCHAR2 ) IS
+  BEGIN
+    DELETE FROM tbl_dems WHERE tbl_name = ANNULER_DEMANDES.tbl_name;
+  END;
+
+
+
+  FUNCTION HAS_DEMANDES RETURN BOOLEAN IS
+    has_dems NUMERIC;
+  BEGIN
+    SELECT count(*) INTO has_dems from tbl_dems where rownum = 1;
+
+    RETURN has_dems = 1;
+  END;
+
+
+
+  PROCEDURE CALCULER_DEMANDES IS
+    dems t_params;
+  BEGIN
+    FOR d IN (
+      SELECT DISTINCT tbl_name FROM tbl_dems
+      ) LOOP
+        dems := PARAMS_FROM_DEMS( d.tbl_name );
+        calculer( d.tbl_name, dems );
+      END LOOP;
+
+    IF HAS_DEMANDES THEN -- pour les boucles !!
+      CALCULER_DEMANDES;
+    END IF;
+  END;
+
+
+
+  -- AUTOMATIC GENERATION --
+
+  -- END OF AUTOMATIC GENERATION --
+
+END UNICAEN_TBL;
\ No newline at end of file