How do we test "IDENTITY" columns? I thought I'd use those since they're supposed to be more standard than SERIAL, but I can't find anything about them in the pgtap docs. I have a table like:
CREATE TABLE jj.history (
history_pk bigint NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
…
);
db=# \d jj.history
Table "jj.history"
Column | Type | Collation | Nullable | Default
------------+--------------------------------+-----------+----------+------------------------------
history_pk | bigint | | not null | generated always as identity
pg_dump says:
CREATE TABLE jj.history (
history_pk bigint NOT NULL,
…
);
ALTER TABLE jj.history ALTER COLUMN history_pk ADD GENERATED ALWAYS AS IDENTITY (
SEQUENCE NAME jj.history_history_pk_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
With pgtap I do:
SELECT has_sequence('jj', 'history_history_pk_seq', 'has history_history_pk_seq');
SELECT col_default_is('jj', 'history', 'history_pk', 'generated always as identity', 'history_pk default');
pg_prove -v gives me:
ok 15 - has history_history_pk_seq
not ok 16 - history_pk default
# Failed test 16: "history_pk default"
# Column jj.history.history_pk has no default
Please note the "has no default" in the error message. Does this mean pgtap doesn't know how to deal with IDENTITY yet or that I'm doing it wrong? If I'm wrong, what is the right way to verify the identity part is there and is the correct form (always -v- default)?
This is with Pg 12.7 and pgtap 1.1.0 (from Ubuntu 20.04.02 packages).
Thanks,
Kevin
GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options
) ]
Do we really need the sequence options? I can kinda sorta see it
each way. Regardless of the "sequence options" (which I'd love some
comments on), col_default_is() definitely needs to be changed.On 8/25/21 9:24 AM, kevin wrote:
Now I just need to dig into pgtap and figure out what to do
with that.
Well, going back to my thoughts on what the use cases are...
1) Is the column GENERATED ... STORED or GENERATED ... AS IDENTITY?
2) If STORED, what's the expression?
3) If AS IDENTITY, is it ALWAYS or BY DEFAULT?
4) If AS IDENTITY, what are the sequence options (if any)?
So spitballing some functions from that...
#1: identity_type_is(table, column, identity_type {STORED,
GENERATED})
#2: identity_stored_expression_is(table, column, expression)
#3: identity_generated_when_is(table, column, when {ALWAYS, BY DEFAULT})
#4: identity_generated_sequence_options_are(table, column, sequence_options)
However, that's just a rough pass and there's definitely some options here...
a) Instead of treating STORED/IDENTITY and ALWAYS/BY DEFAULT as completely separate, we could combine them into something like {STORED, ALWAYS, BY DEFAULT}. That would reduce the number of functions. However I'm not much a fan of this idea since it means pgTap is diverging from how the engine actually works.
b) #1 is technically optional as long as the rest of the functions verify that the identity is of the expected type. IE, if you point identity_stored_expression_is() at a GENERATED ALWAYS identity, it needs to recognize that the type of identity is completely wrong. I don't think there's much precedent for doing this in pgTap though, so probably not a good idea.
c) Obviously I'm compromising English readability in order for all the function names to start with "identity_". Maybe that's not worth doing and the names should be things like "stored_identity_*" and "generated_identity_*"
David, what are your thoughts here?