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: