SQL2003 GENERATED ... AS ... syntax - Mailing list pgsql-hackers

From des@des.no (Dag-Erling Smørgrav)
Subject SQL2003 GENERATED ... AS ... syntax
Date
Msg-id xzp1xw2x5jo.fsf@dwp.des.no
Whole thread Raw
Responses Re: SQL2003 GENERATED ... AS ... syntax
List pgsql-hackers
As previously mentioned, I'm working on implementing [subject].  I
think I've mostly worked it out, but I'm having trouble with the
GENERATED ALWAYS case.

My changes (see attached patch) can be summarized as follows:

 - in backend/utils/adt/misc.c:

   - added a force_default_value() function which takes a string
     argument (the name of the column to force to default) and
     currently does nothing.

 - in backend/parser/gram.y:

   - when GENERATED ... AS ... is encountered in a column definition,
     it adds a node of the new T_Generated type to the constraint
     list.  This node contains a bool that differentiates between BY
     DEFAULT and ALWAYS, and a pointer to a CreateSeqStmt (for
     IDENTITY '(' OptSeqList ')') or a List constructed by the a_expr
     production (for '(' a_expr ')')

 - in backend/parser/analyze.c:

   - factored out the code from transformColumnDefinition() that
     creates the sequence and the DEFAULT constraint into a separate
     CreateSerialColumn() function which takes as one of its arguments
     is a List of sequence options.  The SERIAL code passes in a NIL
     list, while the GENERATED AS IDENTITY code passes in the option
     list from the CreateSeqStmt.

   - added a CreateAlwaysDefaultColumn() function which synthesizes a
     CreateTrigStmt equivalent to CREATE TRIGGER foo BEFORE INSERT ON
     bar FOR EACH ROW EXECUTE PROCEDURE force_default_value ('baz')
     and adds it to the work list.  This function is called by
     transformColumnDefinition() if a Generated node with always set
     to true is encountered.

Now I must be doing something wrong in CreateAlwaysDefaultColumn(),
because the CreateTrigStmt fails to execute:

| des=# create table test ( id int generated always as identity ( minvalue 1000 ), word text );
| NOTICE:  CREATE TABLE will create implicit sequence "test_id_seq" for SERIAL column "test.id"
| NOTICE:  CREATE TABLE will create implicit trigger "test_id_always_default" for column "test.id"
| ERROR:  relation "public.test" does not exist

GENERATED BY DEFAULT AS IDENTITY works fine though, so I must have
done *something* right:

| des=# create table test ( id int generated by default as identity ( minvalue 1000 ), word text );
| NOTICE:  CREATE TABLE will create implicit sequence "test_id_seq" for SERIAL column "test.id"
| CREATE TABLE
| des=# select sequence_name, last_value, min_value, max_value from test_id_seq;
|  sequence_name | last_value | min_value |      max_value
| ---------------+------------+-----------+---------------------
|  test_id_seq   |       1000 |      1000 | 9223372036854775807
| (1 row)
|

On the other hand, I seem to have botched the definition of
force_default_value() in include/catalog/pg_proc.h, because adding the
trigger manually doesn't seem to work either:

| des=# \df force_default_value
|                              List of functions
|  Result data type |   Schema   |        Name         | Argument data types
| ------------------+------------+---------------------+---------------------
|  "trigger"        | pg_catalog | force_default_value | text
| (1 row)
|
| des=# create trigger test_id_always_default before insert on test for each row execute procedure force_default_value
('id');
| ERROR:  function force_default_value() does not exist

Any suggestions?

DES
--
Dag-Erling Smørgrav - des@des.no


Attachment

pgsql-hackers by date:

Previous
From: Carlos Guzman Alvarez
Date:
Subject: Re: Identification of serial fields
Next
From: Rod Taylor
Date:
Subject: Re: SQL2003 GENERATED ... AS ... syntax