[PATCH 1 of 2 saem_ref] [ark] Add a "naan" column to ark table

Denis Laxalde denis.laxalde at logilab.fr
Fri Feb 16 10:07:50 CET 2018


# HG changeset patch
# User Denis Laxalde <denis.laxalde at logilab.fr>
# Date 1518517547 -3600
#      Tue Feb 13 11:25:47 2018 +0100
# Node ID ae9b438859eb66cd5a0edd29b5b98552c041f047
# Parent  4a200f4623e28e2729c07d23cf62772d852ca007
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r ae9b438859eb
# EXP-Topic ark/naan
[ark] Add a "naan" column to ark table

We actually need to ensure uniqueness of the whole ARK identifier
(including the "naan" part).

The only needed change in test is in `unittest_entities.py` where we
changed the "what" value into a number as this is now required by schema
constraint.

diff --git a/cubicweb_saem_ref/entities/__init__.py b/cubicweb_saem_ref/entities/__init__.py
--- a/cubicweb_saem_ref/entities/__init__.py
+++ b/cubicweb_saem_ref/entities/__init__.py
@@ -52,9 +52,10 @@ class ARKIdentifierGenerator(ARKIdentifi
 
     def assign_name(self):
         """Assign and return a new name part of the ARK identifier"""
+        naan = int(self.cw_extra_kwargs['naa_what'])
         cu = self._cw.system_sql(
-            'select * from gen_ark(%s, %s, %s);',
-            (ARK_NAME_LENGTH, ARK_PREFIX, ARK_CONTROLCHAR),
+            'select * from gen_ark(%s, %s, %s, %s);',
+            (naan, ARK_NAME_LENGTH, ARK_PREFIX, ARK_CONTROLCHAR),
         )
         ark_name, = cu.fetchone()
         return ark_name
@@ -77,18 +78,19 @@ class QualifiedARKIdentifierGenerator(AR
                 "ARK identifier for parent entity #%d looks malformattted: %s"
                 % (self.parent_entity.eid, self.parent_entity.ark)
             )
+        naan = int(self.cw_extra_kwargs['naa_what'])
         # Sanity check to make sure we're not producing ARK identifiers with
         # different NAAN for entities that are supposed to be parent of each
         # others.
-        if int(match.group('naan')) != int(self.cw_extra_kwargs['naa_what']):
+        if int(match.group('naan')) != naan:
             raise ValueError(
                 "NAAN of parent entity #%d does not match the value of 'naa_what' parameter: %s"
                 % (self.parent_entity.eid, self.cw_extra_kwargs['naa_what'])
             )
         name = match.group('name')
         cu = self._cw.system_sql(
-            'select * from gen_qualified_ark(%s, %s);',
-            (name, ARK_QUALIFIER_LENGTH, ),
+            'select * from gen_qualified_ark(%s, %s, %s);',
+            (naan, name, ARK_QUALIFIER_LENGTH),
         )
         ark_qualifier, = cu.fetchone()
         return u'/'.join([name, ark_qualifier])
diff --git a/cubicweb_saem_ref/schema/ark.postgres.sql b/cubicweb_saem_ref/schema/ark.postgres.sql
--- a/cubicweb_saem_ref/schema/ark.postgres.sql
+++ b/cubicweb_saem_ref/schema/ark.postgres.sql
@@ -1,7 +1,8 @@
 CREATE TABLE ark (
+    naan INTEGER NOT NULL,
     name TEXT NOT NULL,
     qualifier TEXT NOT NULL DEFAULT '',
-    CONSTRAINT qualified_name PRIMARY KEY (name, qualifier)
+    PRIMARY KEY (naan, name, qualifier)
 );
 
 -- Return a part (name or qualifier) of an ARK identifier of `len` length with
@@ -54,7 +55,7 @@ END;
 -- Insert a record in "ark" table ensuring uniqueness constraints are
 -- fulfilled.
 CREATE OR REPLACE
-FUNCTION gen_ark(len INTEGER, prefix TEXT, control_char TEXT)
+FUNCTION gen_ark(naan INTEGER, len INTEGER, prefix TEXT, control_char TEXT)
 RETURNS TEXT AS $$
 DECLARE
     ark_name TEXT;
@@ -62,7 +63,7 @@ BEGIN
     LOOP
         BEGIN
             INSERT INTO ark
-                VALUES (gen_ark_part(len, prefix, control_char), DEFAULT)
+                VALUES (naan, gen_ark_part(len, prefix, control_char), DEFAULT)
                 RETURNING name INTO ark_name;
             RETURN ark_name;
         EXCEPTION
@@ -75,22 +76,23 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
--- Insert a record in "ark" table from a "base" identifier using a qualifier.
+-- Insert a record in "ark" table from a "naan" value and a "base" identifier
+-- using a qualifier.
 CREATE OR REPLACE
-FUNCTION gen_qualified_ark(base TEXT, len INTEGER)
+FUNCTION gen_qualified_ark(naan_ INTEGER, base TEXT, len INTEGER)
 RETURNS TEXT AS $$
 DECLARE
     ark_qualifier TEXT;
 BEGIN
     PERFORM 1 FROM ark WHERE ark.name = base AND ark.qualifier = '';
     IF NOT FOUND THEN
-        RAISE 'no ark record matching name "%" found', base
+        RAISE 'no ark record matching "%/%" found', naan_, base
         USING ERRCODE = 'invalid_parameter_value';
     END IF;
     LOOP
         BEGIN
             INSERT INTO ark
-                VALUES (base, gen_ark_part(len, '', ''))
+                VALUES (naan_, base, gen_ark_part(len, '', ''))
                 RETURNING qualifier INTO ark_qualifier;
             RETURN ark_qualifier;
         EXCEPTION
diff --git a/test/test_ark.py b/test/test_ark.py
--- a/test/test_ark.py
+++ b/test/test_ark.py
@@ -48,26 +48,26 @@ class ArkServiceTC(testlib.CubicWebTC):
         with self.connect() as conn:
             with conn.cursor() as cu:
                 for _ in range(n):
-                    cu.execute("SELECT * from gen_ark(%s, %s, %s);",
-                               (4, 'rf', 'x'))
+                    cu.execute("SELECT * from gen_ark(%s, %s, %s, %s);",
+                               (0, 4, 'rf', 'x'))
                     arks.append(cu.fetchone()[0])
                     conn.commit()
                 cu.execute("SELECT * from ark")
                 r = cu.fetchall()
         self.assertEqual(len(set(r)), n, len(r))
-        self.assertCountEqual([ark for ark, _ in r], arks)
+        self.assertCountEqual([ark for _, ark, _ in r], arks)
 
     def test_qualifier(self):
         def insert(qualifier=None):
             with self.connect() as conn:
                 with conn.cursor() as cu:
-                    cu.execute("INSERT INTO ark VALUES (%s, %s);",
-                               ("he", qualifier))
+                    cu.execute("INSERT INTO ark VALUES (%s, %s, %s);",
+                               (0, "he", qualifier))
         insert("ah")
         with self.assertRaises(psycopg2.IntegrityError) as cm:
             insert("ah")
         self.assertIn(
-            'duplicate key value violates unique constraint "qualified_name"',
+            'duplicate key value violates unique constraint',
             str(cm.exception),
         )
         insert("he")
@@ -76,12 +76,12 @@ class ArkServiceTC(testlib.CubicWebTC):
         def insert():
             with self.connect() as conn:
                 with conn.cursor() as cu:
-                    cu.execute("INSERT INTO ark VALUES ('he', 'aha');")
+                    cu.execute("INSERT INTO ark VALUES (42, 'he', 'aha');")
         insert()
         with self.assertRaises(psycopg2.IntegrityError) as cm:
             insert()
         self.assertIn(
-            'duplicate key value violates unique constraint "qualified_name"',
+            'duplicate key value violates unique constraint',
             str(cm.exception),
         )
 
@@ -89,22 +89,22 @@ class ArkServiceTC(testlib.CubicWebTC):
         with self.connect() as conn:
             with conn.cursor() as cu:
                 with self.assertRaises(psycopg2.DataError) as cm:
-                    cu.execute("SELECT * FROM gen_qualified_ark(%s, %s);",
-                               ("doesnotexist", 3))
-        self.assertIn('no ark record matching name "doesnotexist" found',
+                    cu.execute("SELECT * FROM gen_qualified_ark(%s, %s, %s);",
+                               (1, "doesnotexist", 3))
+        self.assertIn('no ark record matching "1/doesnotexist" found',
                       str(cm.exception))
 
     def test_generate_qualifier_name_existing(self):
         with self.connect() as conn:
             with conn.cursor() as cu:
-                cu.execute("INSERT INTO ark VALUES (%s, DEFAULT);",
-                           ("exists", ))
-                cu.execute("SELECT * FROM gen_qualified_ark(%s, %s);",
-                           ("exists", 3))
+                cu.execute("INSERT INTO ark VALUES (%s, %s, DEFAULT);",
+                           (12345, "exists", ))
+                cu.execute("SELECT * FROM gen_qualified_ark(%s, %s, %s);",
+                           (12345, "exists", 3))
                 cu.execute("SELECT * FROM ark"
-                           " WHERE ark.name = 'exists'"
+                           " WHERE ark.naan = 12345 AND ark.name = 'exists'"
                            " AND NOT ark.qualifier = '';")
-                (_, qualifier), = cu.fetchall()
+                (_, _, qualifier), = cu.fetchall()
         self.assertEqual(len(qualifier), 3, qualifier)
 
 
diff --git a/test/unittest_entities.py b/test/unittest_entities.py
--- a/test/unittest_entities.py
+++ b/test/unittest_entities.py
@@ -50,7 +50,7 @@ class ArkGeneratorTC(CubicWebTC):
     configcls = PostgresApptestConfiguration
 
     def test(self):
-        what = 'saemref-test'
+        what = '31400'
         with self.admin_access.repo_cnx() as cnx:
             generator = self.vreg['adapters'].select(
                 'IARKGenerator', cnx, naa_what=what)



More information about the saem-devel mailing list