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

Philippe Pepiot philippe.pepiot at logilab.fr
Fri Feb 16 12:22:09 CET 2018


On 16/02/2018, Denis Laxalde wrote:
> # 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)

Why you dropped the explicit name of the constraint ?
Postgres will surely name it ark_pkey but there is no
guarantee on this. Having an explicit name will simplify future
migrations of the schema.

>  );
>  
>  -- 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