Thread: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

[HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
Attached are patches to add an ALWAYS DEFERRED option to CONSTRAINTs and
CONSTRAINT TRIGGERs, meaning: SET CONSTRAINTS .. IMMEDIATE will not make
immediate any constraint/trigger that is declared as ALWAYS DEFERRED.

I.e., the opposite of NOT DEFERRED.  Perhaps I should make this NOT
IMMEDIATE?  Making it NOT IMMEDIATE has the benefit of not having to
change the precedence of ALWAYS to avoid a shift/reduce conflict...  It
may also be more in keeping with NOT DEFERRED.

Motivation:

 - I have trigger procedures that must run at the end of the transaction
   (after the last statement prior to COMMIT sent by the client/user),
   which I make DEFERRABLE, INITIALLY DEFERRED CONSTRAINT TRIGGERs out
   of, but SET CONSTRAINTS can be used to foil my triggers.  I have
   written SQL code to detect that constraint triggers have fired too
   soon, but I'd rather not need it.

 - Symmetry.  If we can have NOT DEFERRABLE constraints, why not also
   NOT IMMEDIABLE?  :)  Naturally "immediable" is not a word, but you
   get the point.

 - To learn my way around PostgreSQL source code in preparation for
   other contributions.

Anyways, this patch is NOT passing tests at the moment, and I'm not sure
why.  I'm sure I can figure it out, but first I need to understand the
failures.  E.g., I see this sort of difference:

   \d testschema.test_index1
   Index "testschema.test_index1"
    Column |  Type  | Definition
   --------+--------+------------
    id     | bigint | id
  -btree, for table "testschema.test_default_tab"
  +f, for table "testschema.btree", predicate (test_default_tab)

which means, I think, that I've screwed up in src/bin/psql/describe.c,
don't it's not obvious to me yet how.

Some questions for experienced PostgreSQL developers:

Q0: Is this sort of patch welcomed?

Q1: Should new columns for pg_catalog.pg_constraint go at the end, or may
    they be added in the middle?

Q2: Can I add new columns to information_schema tables, or are there
    standards-compliance issues with that?

Q3: Is the C-style for PG documented somewhere?  (sorry if I missed this)

Q4: Any ideas what I'm doing wrong in this patch series?

Nico
--

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option forconstraints

From
Andreas Joseph Krogh
Date:
På tirsdag 03. oktober 2017 kl. 21:51:30, skrev Nico Williams <nico@cryptonector.com>:
Attached are patches to add an ALWAYS DEFERRED option to CONSTRAINTs and
CONSTRAINT TRIGGERs, meaning: SET CONSTRAINTS .. IMMEDIATE will not make
immediate any constraint/trigger that is declared as ALWAYS DEFERRED.

I.e., the opposite of NOT DEFERRED.  Perhaps I should make this NOT
IMMEDIATE?  Making it NOT IMMEDIATE has the benefit of not having to
change the precedence of ALWAYS to avoid a shift/reduce conflict...  It
may also be more in keeping with NOT DEFERRED.

Motivation:

 - I have trigger procedures that must run at the end of the transaction
   (after the last statement prior to COMMIT sent by the client/user),
   which I make DEFERRABLE, INITIALLY DEFERRED CONSTRAINT TRIGGERs out
   of, but SET CONSTRAINTS can be used to foil my triggers.  I have
   written SQL code to detect that constraint triggers have fired too
   soon, but I'd rather not need it.

 - Symmetry.  If we can have NOT DEFERRABLE constraints, why not also
   NOT IMMEDIABLE?  :)  Naturally "immediable" is not a word, but you
   get the point.

 - To learn my way around PostgreSQL source code in preparation for
   other contributions.

Anyways, this patch is NOT passing tests at the moment, and I'm not sure
why.  I'm sure I can figure it out, but first I need to understand the
failures.  E.g., I see this sort of difference:

   \d testschema.test_index1
   Index "testschema.test_index1"
    Column |  Type  | Definition
   --------+--------+------------
    id     | bigint | id
  -btree, for table "testschema.test_default_tab"
  +f, for table "testschema.btree", predicate (test_default_tab)

which means, I think, that I've screwed up in src/bin/psql/describe.c,
don't it's not obvious to me yet how.

Some questions for experienced PostgreSQL developers:

Q0: Is this sort of patch welcomed?

Q1: Should new columns for pg_catalog.pg_constraint go at the end, or may
    they be added in the middle?

Q2: Can I add new columns to information_schema tables, or are there
    standards-compliance issues with that?

Q3: Is the C-style for PG documented somewhere?  (sorry if I missed this)

Q4: Any ideas what I'm doing wrong in this patch series?

Nico
 
 
+1.
 
While we're in deferrable constraints land...; 
I even more often need deferrable conditional unique-indexes.
In PG you now may have:
ALTER TABLE email_folder ADD CONSTRAINT some_uk UNIQUE  (owner_id, folder_type, name) DEFERRABLE INITIALLY DEFERRED;
 
But this isn't supported:
CREATE UNIQUE INDEX some_uk ON email_folder(owner_id, folder_type, name) WHERE parent_id IS NULL DEFERRABLE INITIALLY DEFERRED;
 
Are there any plans to support this?
 
Thanks.
 
--
Andreas Joseph Krogh
 

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Tue, Oct 03, 2017 at 10:10:59PM +0200, Andreas Joseph Krogh wrote:
> +1.
> 
> While we're in deferrable constraints land...;  I even more often need 
> deferrable conditional unique-indexes.
> In PG you now may have:
> ALTER TABLE email_folder ADD CONSTRAINT some_uk UNIQUE (owner_id, folder_type, 
> name) DEFERRABLE INITIALLY DEFERRED; 
> 
> But this isn't supported:
> CREATE UNIQUE INDEX some_uk ON email_folder(owner_id, folder_type, name) WHERE 
> parent_id IS NULL DEFERRABLE INITIALLY DEFERRED;
> 
> Are there any plans to support this?

Not by me, but I can take a look and, if it is trivial, do it.  At a
quick glance it does look like it should be easy enough to do it, at
least to get started on a patch.  

If I can get some help with my current patch, I'll take a look :)

But yes, I'd like to have full consistency between CREATE and ALTER.
Everything that one can do with CREATE should be possible to do with
ALTER, including IF NOT EXISTS.

Nico
-- 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Tue, Oct 03, 2017 at 02:51:30PM -0500, Nico Williams wrote:
> Anyways, this patch is NOT passing tests at the moment, and I'm not sure
> why.  I'm sure I can figure it out, but first I need to understand the
> failures.  E.g., I see this sort of difference:
> 
>    \d testschema.test_index1
>    Index "testschema.test_index1"
>     Column |  Type  | Definition
>    --------+--------+------------
>     id     | bigint | id
>   -btree, for table "testschema.test_default_tab"
>   +f, for table "testschema.btree", predicate (test_default_tab)
> 
> which means, I think, that I've screwed up in src/bin/psql/describe.c,
> don't it's not obvious to me yet how.

Ah, I needed to adjust references to results columns.  I suspect that
something similar relates to other remaining failures.


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Vik Fearing
Date:
On 10/03/2017 10:10 PM, Andreas Joseph Krogh wrote:
> While we're in deferrable constraints land...; 
> I even more often need deferrable /conditional /unique-indexes.
> In PG you now may have:
> 
> ALTER TABLE email_folder ADD CONSTRAINT some_uk UNIQUE (owner_id, folder_type, name) DEFERRABLE INITIALLY DEFERRED;
> 
>  
> But this isn't supported:
> 
> CREATE UNIQUE INDEX some_uk ON email_folder(owner_id, folder_type, name) WHERE parent_id IS NULL DEFERRABLE INITIALLY
DEFERRED;
> 
> Are there any plans to support this?

I don't want to hijack the thread, but you can do that with exclusion
constraints.
-- 
Vik Fearing                                          +33 6 46 75 15 36
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option forconstraints

From
Andreas Joseph Krogh
Date:
På onsdag 04. oktober 2017 kl. 00:24:19, skrev Vik Fearing <vik.fearing@2ndquadrant.com>:
On 10/03/2017 10:10 PM, Andreas Joseph Krogh wrote:
> While we're in deferrable constraints land...;
> I even more often need deferrable /conditional /unique-indexes.
> In PG you now may have:
>
> ALTER TABLE email_folder ADD CONSTRAINT some_uk UNIQUE (owner_id, folder_type, name) DEFERRABLE INITIALLY DEFERRED;
>

> But this isn't supported:
>
> CREATE UNIQUE INDEX some_uk ON email_folder(owner_id, folder_type, name) WHERE parent_id IS NULL DEFERRABLE INITIALLY DEFERRED;
>
> Are there any plans to support this?

I don't want to hijack the thread, but you can do that with exclusion
constraints.
 
 
True.
 
--
Andreas Joseph Krogh
 

[HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
[make check-world passes.  Tests and docs included.  Should be ready for
code review.]

Attached are patches to add an ALWAYS DEFERRED option to CONSTRAINTs and
CONSTRAINT TRIGGERs, meaning: SET CONSTRAINTS .. IMMEDIATE will not make
immediate any constraint/trigger that is declared as ALWAYS DEFERRED.

I.e., the opposite of NOT DEFERRED.

Motivation:

 - Security.

   One may have triggers they need to always be deferred and they
   cannot give direct PG access because of SET CONSTRAINTS .. IMMEDIATE.

   I have such triggers that must run at the end of the transaction
   (after the last statement prior to COMMIT sent by the client/user),
   which I make DEFERRABLE, INITIALLY DEFERRED CONSTRAINT TRIGGERs.

   I have written SQL code to detect that constraint triggers have fired
   too soon, but I'd rather not need it as it does slow things down (it
   uses DDL event triggers and per-table triggers).

   Making it easier to write secure code DEFERRED CONSTRAINT TRIGGERs
   seems like a good idea to me.

 - Symmetry.

   Not using NOT DEFERRABLE is not the inverse of NOT DEFERRABLE.  There
   is no inverse at this time.

   If we can have NOT DEFERRABLE constraints, why not also the inverse,
   a constraint that cannot be made IMMEDIATE with SET CONSTRAINTs?


I've *not* cleaned up C style issues in surrounding -- I'm not sure
if that's desired.  Not cleaning up makes it easier to see what I
changed.

Some questions for experienced PostgreSQL developers:

Q0: Is this sort of patch welcomed?

Q1: Should new columns for pg_catalog tables go at the end, or may they
    be added in the middle?

    FYI, I'm adding them in the middle, so they are next to related
    columns.

Q2: Can I add new columns to information_schema tables, or are there
    standards-compliance issues with that?

    This is done in the second patch, and it can be dropped safely.

Q3: Perhaps I should make this NOT IMMEDIATE rather than ALWAYS DEFERRED?
    Making it NOT IMMEDIATE has the benefit of not having to change the
    precedence of ALWAYS to avoid a shift/reduce conflict...  It may
    also be more in keeping with NOT DEFERRED.  Thoughts?

Nico
--

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachment

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
Ay, NOT WIP -- I left that in the Subject: by accident.


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
Ah, David Fetter points out that I should also update tabe completion
for psql.  I'll do that at some point.  I notice there's no table
completion for column constraint attributes...  If it's obvious enough
I'll try to fix that too.


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
I accidentally typoed when saving a file.  Here's the new patch with
that typo corrected, changes to information_schema dropped, and with the
addition of tab completion of ALWAYS DEFERRED in psql.

Nico
--

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachment

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
FYI, I've added my patch to the commitfest.

https://commitfest.postgresql.org/15/1319/


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
Rebased (there were conflicts in the SGML files).

Nico
--

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachment

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Peter Eisentraut
Date:
I haven't really thought about this feature too hard; I just want to
give you a couple of code comments.

I think the catalog structure, and relatedly also the parser structures,
could be made more compact.  We currently have condeferrable and
condeferred to represent three valid states (NOT DEFERRABLE, DEFERRABLE
INITIALLY IMMEDIATE, DEFERRABLE INITIALLY DEFERRED).  You are adding
conalwaysdeferred, but you are adding only additional state (ALWAYS
DEFERRED).  So we end up with three bool fields to represent four
states.  I think this should all be rolled into one char field with four
states.

In psql and pg_dump, if you are query new catalog fields, you need to
have a version check to have a different query for >=PG11.  (This would
likely apply whether you adopt my suggestion above or not.)

Maybe a test case in pg_dump would be useful.

Other than that, this looks like a pretty complete patch.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Thu, Nov 02, 2017 at 04:20:19PM -0400, Peter Eisentraut wrote:
> I haven't really thought about this feature too hard; I just want to
> give you a couple of code comments.

Thanks!

> I think the catalog structure, and relatedly also the parser structures,
> could be made more compact.  We currently have condeferrable and
> condeferred to represent three valid states (NOT DEFERRABLE, DEFERRABLE
> INITIALLY IMMEDIATE, DEFERRABLE INITIALLY DEFERRED).  You are adding
> conalwaysdeferred, but you are adding only additional state (ALWAYS
> DEFERRED).  So we end up with three bool fields to represent four
> states.  I think this should all be rolled into one char field with four
> states.

I thought about this.  I couldn't see a way to make the two existing
boolean columns have a combination meaning "ALWAYS DEFERRED" that might
not break something else.

Since (condeferred AND NOT condeferrable) is an impossible combination
today, I could use it to mean ALWAYS DEFERRED.  I'm not sure how safe
that would be.  And it does seem like a weird way to express ALWAYS
DEFERRED, though it would work.

Replacing condeferred and condeferrable with a char columns also
occurred to me, and though I assume backwards-incompatible changes to
pg_catalog tables are fair game, I assumed everyone would prefer
avoiding such changes where possible.

Also, a backwards-incompatible change to the table would significantly
enlarge the patch, as more version checks would be needed, particularly
regarding upgrades (which are otherwise trivial).

I felt adding a new column was probably safest.  I'll make a backwards-
incompatible change if requested, naturally, but I guess I'd want to
get wider consensus on that, as I fear others may not agree.  That fear
may just be due to my ignorance of the community's preference as to
pg_catalog backwards-compatibility vs. cleanliness.

Hmmm, must I do anything special about _downgrades_?  Does PostgreSQL
support downgrades?

> In psql and pg_dump, if you are query new catalog fields, you need to
> have a version check to have a different query for >=PG11.  (This would
> likely apply whether you adopt my suggestion above or not.)

Ah, yes, of course.  I will add such a check.

> Maybe a test case in pg_dump would be useful.

Will do.

> Other than that, this looks like a pretty complete patch.

Thanks for the review!  It's a small-ish patch, and my very first for
PG.  It was fun writing it.  I greatly appreciate that PG source is easy
to read.

Nico
-- 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Peter Eisentraut
Date:
On 11/2/17 16:54, Nico Williams wrote:
> Replacing condeferred and condeferrable with a char columns also
> occurred to me, and though I assume backwards-incompatible changes to
> pg_catalog tables are fair game, I assumed everyone would prefer
> avoiding such changes where possible.

I don't think there is an overriding mandate to avoid such catalog
changes.  Consider old clients that don't know about your new column.
They might look at the catalog entries and derive information about a
constraint, not being aware that there is additional information in
another column that overrides that.  So in such cases it's arguably
better to make a break.

(In any case, it might be worth waiting for a review of the rest of the
patch before taking on a significant rewrite of the catalog structures.)

> Hmmm, must I do anything special about _downgrades_?  Does PostgreSQL
> support downgrades?

no

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Fri, Nov 03, 2017 at 01:41:45PM -0400, Peter Eisentraut wrote:
> On 11/2/17 16:54, Nico Williams wrote:
> > Replacing condeferred and condeferrable with a char columns also
> > occurred to me, and though I assume backwards-incompatible changes to
> > pg_catalog tables are fair game, I assumed everyone would prefer
> > avoiding such changes where possible.
> 
> I don't think there is an overriding mandate to avoid such catalog
> changes.  Consider old clients that don't know about your new column.
> They might look at the catalog entries and derive information about a
> constraint, not being aware that there is additional information in
> another column that overrides that.  So in such cases it's arguably
> better to make a break.

Makes sense.

> (In any case, it might be worth waiting for a review of the rest of the
> patch before taking on a significant rewrite of the catalog structures.)

I'll wait then :)

When you're done with that I'll make this change (replacing those three
bool columns with a single char column).

> > Hmmm, must I do anything special about _downgrades_?  Does PostgreSQL
> > support downgrades?
> 
> no

Oh good.  Thanks for clarifying that.

Nico
-- 


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Thomas Munro
Date:
On Fri, Oct 20, 2017 at 9:05 AM, Nico Williams <nico@cryptonector.com> wrote:
> Rebased (there were conflicts in the SGML files).

Hi Nico

FYI that version has some stray absolute paths in constraints.source:

-COPY COPY_TBL FROM '@abs_srcdir@/data/constro.data';
+COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constro.data';

-COPY COPY_TBL FROM '@abs_srcdir@/data/constrf.data';
+COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constrf.data';

-- 
Thomas Munro
http://www.enterprisedb.com


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Mon, Nov 06, 2017 at 05:50:21PM +1300, Thomas Munro wrote:
> On Fri, Oct 20, 2017 at 9:05 AM, Nico Williams <nico@cryptonector.com> wrote:
> > Rebased (there were conflicts in the SGML files).
> 
> Hi Nico
> 
> FYI that version has some stray absolute paths in constraints.source:
> 
> -COPY COPY_TBL FROM '@abs_srcdir@/data/constro.data';
> +COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constro.data';
> 
> -COPY COPY_TBL FROM '@abs_srcdir@/data/constrf.data';
> +COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constrf.data';

Oops!  Thanks for catching that!


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] [PATCH] Add ALWAYS DEFERRED option for constraints

From
Michael Paquier
Date:
On Wed, Nov 8, 2017 at 8:30 AM, Nico Williams <nico@cryptonector.com> wrote:
> On Mon, Nov 06, 2017 at 05:50:21PM +1300, Thomas Munro wrote:
>> On Fri, Oct 20, 2017 at 9:05 AM, Nico Williams <nico@cryptonector.com> wrote:
>> > Rebased (there were conflicts in the SGML files).
>>
>> Hi Nico
>>
>> FYI that version has some stray absolute paths in constraints.source:
>>
>> -COPY COPY_TBL FROM '@abs_srcdir@/data/constro.data';
>> +COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constro.data';
>>
>> -COPY COPY_TBL FROM '@abs_srcdir@/data/constrf.data';
>> +COPY COPY_TBL FROM '/home/nico/ws/postgres/src/test/regress/data/constrf.data';
>
> Oops!  Thanks for catching that!

Those are not fixed yet, and it has been three weeks since this
report, so I am marking this patch as returned with feedback. Of
course feel free to send an updated version if you can get into it.
-- 
Michael


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
[Re-send; first attempt appears to have hit /dev/null somewhere.  My
apologies if you get two copies.]

I've finally gotten around to rebasing this patch and making the change
that was requested, which was: merge the now-would-be-three deferral-
related bool columns in various pg_catalog tables into one char column.

Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
(deferral).

All tests (make check) pass.

Sorry for the delay in doing this!

Incidentally, I had to do commit-by-commit rebasing to make the rebase
easier.  I have a shell function I use for this, if anyone wants a copy
of it -- sometimes it's much easier to do this than to do one huge jump.

Nico
--

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Robbie Harwood
Date:
Nico Williams <nico@cryptonector.com> writes:

> [Re-send; first attempt appears to have hit /dev/null somewhere.  My
> apologies if you get two copies.]
>
> I've finally gotten around to rebasing this patch and making the change
> that was requested, which was: merge the now-would-be-three deferral-
> related bool columns in various pg_catalog tables into one char column.
>
> Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
> (deferral).

This design seems correct to me.  I have a couple questions inline, and
some nits to go with them.

> All tests (make check) pass.

Thank you for adding tests!

> diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
> index 3ed9021..e82e39b 100644
> --- a/doc/src/sgml/catalogs.sgml
> +++ b/doc/src/sgml/catalogs.sgml
> @@ -2239,17 +2239,15 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
>       </row>
>
>       <row>
> -      <entry><structfield>condeferrable</structfield></entry>
> -      <entry><type>bool</type></entry>
> -      <entry></entry>
> -      <entry>Is the constraint deferrable?</entry>
> -     </row>
> -
> -     <row>
> -      <entry><structfield>condeferred</structfield></entry>
> -      <entry><type>bool</type></entry>
> +      <entry><structfield>condeferral</structfield></entry>
> +      <entry><type>char</type></entry>
>        <entry></entry>
> -      <entry>Is the constraint deferred by default?</entry>
> +      <entry>Constraint deferral option:
> +            <literal>a</literal> = always deferred,
> +            <literal>d</literal> = deferrable,
> +            <literal>d</literal> = deferrable initially deferred,

From the rest of the code, I think this is supposed to be 'i', not 'd'.

> +            <literal>n</literal> = not deferrable
> +          </entry>
>       </row>
>
>       <row>

> diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
> index 8b276bc..795a7a9 100644
> --- a/src/backend/catalog/index.c
> +++ b/src/backend/catalog/index.c
> @@ -1070,6 +1070,7 @@ index_create(Relation heapRelation,
>
>                  recordDependencyOn(&myself, &referenced, deptype);
>              }
> +            Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);

What does this ensure, and why is it in this part of the code?  We're in
the `else` branch here - isn't this always the case (i.e., Assert can
never fire), since `flags` isn't manipulated in this block?

>          }
>
>          /* Store dependency on parent index, if any */

> diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
> index f4e69f4..bde6199 100644
> --- a/src/backend/catalog/information_schema.sql
> +++ b/src/backend/catalog/information_schema.sql
> @@ -891,10 +891,14 @@ CREATE VIEW domain_constraints AS
>             CAST(current_database() AS sql_identifier) AS domain_catalog,
>             CAST(n.nspname AS sql_identifier) AS domain_schema,
>             CAST(t.typname AS sql_identifier) AS domain_name,
> -           CAST(CASE WHEN condeferrable THEN 'YES' ELSE 'NO' END
> +           CAST(CASE WHEN condeferral = 'n' THEN 'NO' ELSE 'YES' END
>               AS yes_or_no) AS is_deferrable,
> -           CAST(CASE WHEN condeferred THEN 'YES' ELSE 'NO' END
> +           CAST(CASE WHEN condeferral = 'i' OR condeferral = 'a' THEN 'YES' ELSE 'NO' END
>               AS yes_or_no) AS initially_deferred
> +       /*
> +        * XXX Can we add is_always_deferred here?  Are there
> +        * standards considerations?
> +        */

I'm not familiar enough to speak to this.  Hopefully someone else can.
Absent other input, I think we should add is_always_deferred.  (And if
we were building this today, probably just expose a single character
instead of three booleans.)

>      FROM pg_namespace rs, pg_namespace n, pg_constraint con, pg_type t
>      WHERE rs.oid = con.connamespace
>            AND n.oid = t.typnamespace

> diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
> index 57519fe..41dc6a4 100644
> --- a/src/backend/commands/trigger.c
> +++ b/src/backend/commands/trigger.c
> @@ -3632,6 +3627,7 @@ typedef struct AfterTriggerSharedData
>      TriggerEvent ats_event;        /* event type indicator, see trigger.h */
>      Oid            ats_tgoid;        /* the trigger's ID */
>      Oid            ats_relid;        /* the relation it's on */
> +    bool            ats_alwaysdeferred;    /* whether this can be deferred */

"Whether this must be deferred"?  Also, I'm not sure what this is for -
it doesn't seem to be used anywhere.

>      CommandId    ats_firing_id;    /* ID for firing cycle */
>      struct AfterTriggersTableData *ats_table;    /* transition table access */
>  } AfterTriggerSharedData;

> diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
> index 90dfac2..dab721a 100644
> --- a/src/backend/parser/gram.y
> +++ b/src/backend/parser/gram.y
> @@ -184,8 +185,8 @@ static void SplitColQualList(List *qualList,
>                               List **constraintList, CollateClause **collClause,
>                               core_yyscan_t yyscanner);
>  static void processCASbits(int cas_bits, int location, const char *constrType,
> -               bool *deferrable, bool *initdeferred, bool *not_valid,
> -               bool *no_inherit, core_yyscan_t yyscanner);
> +               char *deferral,
> +               bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner);

Can you fix the wrapping on this?

>  static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
>
>  %}
> @@ -5538,17 +5568,24 @@ ConstraintAttributeSpec:
>                      int        newspec = $1 | $2;
>
>                      /* special message for this case */
> -                    if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE |
CAS_INITIALLY_DEFERRED))
> +                    if ((newspec & CAS_NOT_DEFERRABLE) &&
> +                        (newspec & (CAS_INITIALLY_DEFERRED | CAS_ALWAYS_DEFERRED)))
>                          ereport(ERROR,
>                                  (errcode(ERRCODE_SYNTAX_ERROR),
>                                   errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
>                                   parser_errposition(@2)));
>                      /* generic message for other conflicts */
> +                    if ((newspec & CAS_ALWAYS_DEFERRED) &&
> +                        (newspec & (CAS_INITIALLY_IMMEDIATE)))
> +                        ereport(ERROR,
> +                                (errcode(ERRCODE_SYNTAX_ERROR),
> +                                 errmsg("conflicting constraint properties 1"),
> +                                 parser_errposition(@2)));
>                      if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)
||
>                          (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE |
CAS_INITIALLY_DEFERRED))
>                          ereport(ERROR,
>                                  (errcode(ERRCODE_SYNTAX_ERROR),
> -                                 errmsg("conflicting constraint properties"),
> +                                 errmsg("conflicting constraint properties 2"),

I'd prefer you just repeat the message (or make them more situationally
descriptive), rather than appending a number.  (Repeating error messages
is in keeping with the style here.)

>                                   parser_errposition(@2)));
>                      $$ = newspec;
>                  }
> @@ -16197,34 +16234,41 @@ SplitColQualList(List *qualList,
>   */
>  static void
>  processCASbits(int cas_bits, int location, const char *constrType,
> -               bool *deferrable, bool *initdeferred, bool *not_valid,
> -               bool *no_inherit, core_yyscan_t yyscanner)
> +               char *deferral,
> +               bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner)

Line wrapping?

>  {
>      /* defaults */
> -    if (deferrable)
> -        *deferrable = false;
> -    if (initdeferred)
> -        *initdeferred = false;
> +    if (deferral)
> +        *deferral = 'n';
>      if (not_valid)
>          *not_valid = false;
>
> -    if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED))
> +    if (cas_bits & CAS_ALWAYS_DEFERRED)
>      {
> -        if (deferrable)
> -            *deferrable = true;
> +        if (deferral)
> +            *deferral = 'a';
>          else
>              ereport(ERROR,
>                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
>                       /* translator: %s is CHECK, UNIQUE, or similar */
> -                     errmsg("%s constraints cannot be marked DEFERRABLE",
> +                     errmsg("%s constraints cannot be marked ALWAYS DEFERRED",
>                              constrType),
>                       parser_errposition(location)));
> -    }
> -
> -    if (cas_bits & CAS_INITIALLY_DEFERRED)
> +    } else if (cas_bits & CAS_INITIALLY_DEFERRED)

Style on this file doesn't cuddle `else`.  (i.e., `else if (cond)` gets its own
line without any braces on it.)

> +    {
> +        if (deferral)
> +            *deferral = 'i';
> +        else
> +            ereport(ERROR,
> +                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> +                     /* translator: %s is CHECK, UNIQUE, or similar */
> +                     errmsg("%s constraints cannot be marked INITIALLY DEFERRED",
> +                            constrType),
> +                     parser_errposition(location)));
> +    } else if (cas_bits & CAS_DEFERRABLE)
>      {
> -        if (initdeferred)
> -            *initdeferred = true;
> +        if (deferral)
> +            *deferral = 'd';
>          else
>              ereport(ERROR,
>                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

Thanks,
--Robbie

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Tue, Jun 26, 2018 at 04:54:13PM -0400, Robbie Harwood wrote:
> Nico Williams <nico@cryptonector.com> writes:
> 
> > [Re-send; first attempt appears to have hit /dev/null somewhere.  My
> > apologies if you get two copies.]
> >
> > I've finally gotten around to rebasing this patch and making the change
> > that was requested, which was: merge the now-would-be-three deferral-
> > related bool columns in various pg_catalog tables into one char column.
> >
> > Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
> > (deferral).
> 
> This design seems correct to me.  I have a couple questions inline, and
> some nits to go with them.

Thanks for the review.  I'm traveling (on vacation).  I'll try to get to
your comments within a week.  Thanks!


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Tue, Jun 26, 2018 at 04:54:13PM -0400, Robbie Harwood wrote:
> Nico Williams <nico@cryptonector.com> writes:
> 
> > [Re-send; first attempt appears to have hit /dev/null somewhere.  My
> > apologies if you get two copies.]
> >
> > I've finally gotten around to rebasing this patch and making the change
> > that was requested, which was: merge the now-would-be-three deferral-
> > related bool columns in various pg_catalog tables into one char column.
> >
> > Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
> > (deferral).
> 
> This design seems correct to me.  I have a couple questions inline, and
> some nits to go with them.

Thanks.  Replies below.

> > All tests (make check) pass.
> 
> Thank you for adding tests!

Well, yeah :)

> > diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
> > index 3ed9021..e82e39b 100644
> > --- a/doc/src/sgml/catalogs.sgml
> > +++ b/doc/src/sgml/catalogs.sgml
> > @@ -2239,17 +2239,15 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
> >       </row>
> >  
> >       <row>
> > -      <entry><structfield>condeferrable</structfield></entry>
> > -      <entry><type>bool</type></entry>
> > -      <entry></entry>
> > -      <entry>Is the constraint deferrable?</entry>
> > -     </row>
> > -
> > -     <row>
> > -      <entry><structfield>condeferred</structfield></entry>
> > -      <entry><type>bool</type></entry>
> > +      <entry><structfield>condeferral</structfield></entry>
> > +      <entry><type>char</type></entry>
> >        <entry></entry>
> > -      <entry>Is the constraint deferred by default?</entry>
> > +      <entry>Constraint deferral option:
> > +            <literal>a</literal> = always deferred,
> > +            <literal>d</literal> = deferrable,
> > +            <literal>d</literal> = deferrable initially deferred,
> 
> From the rest of the code, I think this is supposed to be 'i', not 'd'.

Oh yes, good catch.

> > +            <literal>n</literal> = not deferrable
> > +          </entry>
> >       </row>
> >  
> >       <row>
> 
> > diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
> > index 8b276bc..795a7a9 100644
> > --- a/src/backend/catalog/index.c
> > +++ b/src/backend/catalog/index.c
> > @@ -1070,6 +1070,7 @@ index_create(Relation heapRelation,
> >  
> >                  recordDependencyOn(&myself, &referenced, deptype);
> >              }
> > +            Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
> 
> What does this ensure, and why is it in this part of the code?  We're in
> the `else` branch here - isn't this always the case (i.e., Assert can
> never fire), since `flags` isn't manipulated in this block?

Oy, nothing.  I think that's a cut-n-paste error.

I'll remove it.

> >          }
> >  
> >          /* Store dependency on parent index, if any */
> 
> > diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
> > index f4e69f4..bde6199 100644
> > --- a/src/backend/catalog/information_schema.sql
> > +++ b/src/backend/catalog/information_schema.sql
> > @@ -891,10 +891,14 @@ CREATE VIEW domain_constraints AS
> >             CAST(current_database() AS sql_identifier) AS domain_catalog,
> >             CAST(n.nspname AS sql_identifier) AS domain_schema,
> >             CAST(t.typname AS sql_identifier) AS domain_name,
> > -           CAST(CASE WHEN condeferrable THEN 'YES' ELSE 'NO' END
> > +           CAST(CASE WHEN condeferral = 'n' THEN 'NO' ELSE 'YES' END
> >               AS yes_or_no) AS is_deferrable,
> > -           CAST(CASE WHEN condeferred THEN 'YES' ELSE 'NO' END
> > +           CAST(CASE WHEN condeferral = 'i' OR condeferral = 'a' THEN 'YES' ELSE 'NO' END
> >               AS yes_or_no) AS initially_deferred
> > +       /*
> > +        * XXX Can we add is_always_deferred here?  Are there
> > +        * standards considerations?
> > +        */
> 
> I'm not familiar enough to speak to this.  Hopefully someone else can.
> Absent other input, I think we should add is_always_deferred.  (And if
> we were building this today, probably just expose a single character
> instead of three booleans.)

I had found the answer ("yes") in the history of this file but forgot to
remove the comment while rebasing.  I'll remove the comment.

> >      FROM pg_namespace rs, pg_namespace n, pg_constraint con, pg_type t
> >      WHERE rs.oid = con.connamespace
> >            AND n.oid = t.typnamespace
> 
> > diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
> > index 57519fe..41dc6a4 100644
> > --- a/src/backend/commands/trigger.c
> > +++ b/src/backend/commands/trigger.c
> > @@ -3632,6 +3627,7 @@ typedef struct AfterTriggerSharedData
> >      TriggerEvent ats_event;        /* event type indicator, see trigger.h */
> >      Oid            ats_tgoid;        /* the trigger's ID */
> >      Oid            ats_relid;        /* the relation it's on */
> > +    bool            ats_alwaysdeferred;    /* whether this can be deferred */
> 
> "Whether this must be deferred"?  Also, I'm not sure what this is for -
> it doesn't seem to be used anywhere.

Ah, this became unused during the rebase.  I'll remove it.

> >      CommandId    ats_firing_id;    /* ID for firing cycle */
> >      struct AfterTriggersTableData *ats_table;    /* transition table access */
> >  } AfterTriggerSharedData;
> 
> > diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
> > index 90dfac2..dab721a 100644
> > --- a/src/backend/parser/gram.y
> > +++ b/src/backend/parser/gram.y
> > @@ -184,8 +185,8 @@ static void SplitColQualList(List *qualList,
> >                               List **constraintList, CollateClause **collClause,
> >                               core_yyscan_t yyscanner);
> >  static void processCASbits(int cas_bits, int location, const char *constrType,
> > -               bool *deferrable, bool *initdeferred, bool *not_valid,
> > -               bool *no_inherit, core_yyscan_t yyscanner);
> > +               char *deferral,
> > +               bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner);
> 
> Can you fix the wrapping on this?

Maybe!  :)  I couldn't quite figure out what it should be.  There
doesn't seem to be a consistent style of wrapping.

> >  static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
> >  
> >  %}
> > @@ -5538,17 +5568,24 @@ ConstraintAttributeSpec:
> >                      int        newspec = $1 | $2;
> >  
> >                      /* special message for this case */
> > -                    if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE |
CAS_INITIALLY_DEFERRED))
> > +                    if ((newspec & CAS_NOT_DEFERRABLE) &&
> > +                        (newspec & (CAS_INITIALLY_DEFERRED | CAS_ALWAYS_DEFERRED)))
> >                          ereport(ERROR,
> >                                  (errcode(ERRCODE_SYNTAX_ERROR),
> >                                   errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
> >                                   parser_errposition(@2)));
> >                      /* generic message for other conflicts */
> > +                    if ((newspec & CAS_ALWAYS_DEFERRED) &&
> > +                        (newspec & (CAS_INITIALLY_IMMEDIATE)))
> > +                        ereport(ERROR,
> > +                                (errcode(ERRCODE_SYNTAX_ERROR),
> > +                                 errmsg("conflicting constraint properties 1"),
> > +                                 parser_errposition(@2)));
> >                      if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)
||
> >                          (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE
|CAS_INITIALLY_DEFERRED))
 
> >                          ereport(ERROR,
> >                                  (errcode(ERRCODE_SYNTAX_ERROR),
> > -                                 errmsg("conflicting constraint properties"),
> > +                                 errmsg("conflicting constraint properties 2"),
> 
> I'd prefer you just repeat the message (or make them more situationally
> descriptive), rather than appending a number.  (Repeating error messages
> is in keeping with the style here.)

Oy, I forgot about these.  The number was a bread crumb I forgot to
cleanup :(  So sorry about that.

> >                                   parser_errposition(@2)));
> >                      $$ = newspec;
> >                  }
> > @@ -16197,34 +16234,41 @@ SplitColQualList(List *qualList,
> >   */
> >  static void
> >  processCASbits(int cas_bits, int location, const char *constrType,
> > -               bool *deferrable, bool *initdeferred, bool *not_valid,
> > -               bool *no_inherit, core_yyscan_t yyscanner)
> > +               char *deferral,
> > +               bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner)
> 
> Line wrapping?
> 
> >  {
> >      /* defaults */
> > -    if (deferrable)
> > -        *deferrable = false;
> > -    if (initdeferred)
> > -        *initdeferred = false;
> > +    if (deferral)
> > +        *deferral = 'n';
> >      if (not_valid)
> >          *not_valid = false;
> >  
> > -    if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED))
> > +    if (cas_bits & CAS_ALWAYS_DEFERRED)
> >      {
> > -        if (deferrable)
> > -            *deferrable = true;
> > +        if (deferral)
> > +            *deferral = 'a';
> >          else
> >              ereport(ERROR,
> >                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> >                       /* translator: %s is CHECK, UNIQUE, or similar */
> > -                     errmsg("%s constraints cannot be marked DEFERRABLE",
> > +                     errmsg("%s constraints cannot be marked ALWAYS DEFERRED",
> >                              constrType),
> >                       parser_errposition(location)));
> > -    }
> > -
> > -    if (cas_bits & CAS_INITIALLY_DEFERRED)
> > +    } else if (cas_bits & CAS_INITIALLY_DEFERRED)
> 
> Style on this file doesn't cuddle `else`.  (i.e., `else if (cond)` gets its own
> line without any braces on it.)

OK.

> > +    {
> > +        if (deferral)
> > +            *deferral = 'i';
> > +        else
> > +            ereport(ERROR,
> > +                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> > +                     /* translator: %s is CHECK, UNIQUE, or similar */
> > +                     errmsg("%s constraints cannot be marked INITIALLY DEFERRED",
> > +                            constrType),
> > +                     parser_errposition(location)));
> > +    } else if (cas_bits & CAS_DEFERRABLE)
> >      {
> > -        if (initdeferred)
> > -            *initdeferred = true;
> > +        if (deferral)
> > +            *deferral = 'd';
> >          else
> >              ereport(ERROR,
> >                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> 
> Thanks,
> --Robbie

Thank you.  I'll rebase, update, and post a new patch soon.

Nico
-- 


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Alvaro Herrera
Date:
On 2018-Jun-06, Nico Williams wrote:

> I've finally gotten around to rebasing this patch and making the change
> that was requested, which was: merge the now-would-be-three deferral-
> related bool columns in various pg_catalog tables into one char column.
> 
> Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
> (deferral).

Nice stuff.

Please add #defines for the chars in pg_constraint.h instead of using
the values directly in the source.  Also, catalogs.sgml has a typo in
one of the values.

What happens if you do SET CONSTRAINTS ALL IMMEDIATE and you have one of
these constraints?  I expect that it silently does not alter that
constraint, but you didn't change that manpage.

I suggest not to include psql/tab-complete changes with your main patch.
If you want to update it, split it out to its own patch.  Committer can
choose to include it in one commit or not (I'm mildly inclined not to,
but I'm probably inconsistent about it), but for review IMO it's better
not to mix things -- It's way too easy to get entangled in silly details
while editing that code, and it's not critical anyway.

> Incidentally, I had to do commit-by-commit rebasing to make the rebase
> easier.  I have a shell function I use for this, if anyone wants a copy
> of it -- sometimes it's much easier to do this than to do one huge jump.

I've done this manually a few times.  Please share, I'm curious.

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Wed, Jul 11, 2018 at 03:13:30PM -0400, Alvaro Herrera wrote:
> On 2018-Jun-06, Nico Williams wrote:
> > I've finally gotten around to rebasing this patch and making the change
> > that was requested, which was: merge the now-would-be-three deferral-
> > related bool columns in various pg_catalog tables into one char column.
> > 
> > Instead of (deferrable, initdeferred, alwaysdeferred), now there is just
> > (deferral).
> 
> Nice stuff.
> 
> Please add #defines for the chars in pg_constraint.h instead of using
> the values directly in the source.  Also, catalogs.sgml has a typo in
> one of the values.
> 
> What happens if you do SET CONSTRAINTS ALL IMMEDIATE and you have one of
> these constraints?  I expect that it silently does not alter that
> constraint, but you didn't change that manpage.

Correct, that's the idea, that it should be possible to write deferred
constraints/triggers which users cannot make immediate.  For example, an
audit extension that logs changes via FOR EACH ROW ALWAYS DEFERRED, or
my PoC COMMIT TRIGGER implementation (which depends on deferred
triggers).

I missed that there is a page for SET CONSTRAINTS!  I'll update it.

> I suggest not to include psql/tab-complete changes with your main patch.
> If you want to update it, split it out to its own patch.  Committer can
> choose to include it in one commit or not (I'm mildly inclined not to,
> but I'm probably inconsistent about it), but for review IMO it's better
> not to mix things -- It's way too easy to get entangled in silly details
> while editing that code, and it's not critical anyway.

OK, sure, though, of course, the committer could always leave that out
themselves, no?

To me though it seems that the change should be complete.

> > Incidentally, I had to do commit-by-commit rebasing to make the rebase
> > easier.  I have a shell function I use for this, if anyone wants a copy
> > of it -- sometimes it's much easier to do this than to do one huge jump.
> 
> I've done this manually a few times.  Please share, I'm curious.

OK, attached is my latest version of that script, though this one is a
bit changed from the one I used.  This version tries to be faster / more
efficient by first doing 1 commit, then 2, then 3, and so on, and on
conflict aborts and halves N to try again.  The idea is to only have to
merge conflicts at each commit where conflicts arise, never resolving
conflicts across more than one commit -- this makes is much easier to
reason about conflicts!

Note that the script is actually a shell function, and that it keeps
state in shel variables.  A better implementation would do the sort of
thing that git(1) itself does to keep rebase state.

Nico
--

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
On Wed, Jul 11, 2018 at 01:41:12PM -0500, Nico Williams wrote:
> > > @@ -5538,17 +5568,24 @@ ConstraintAttributeSpec:
> > >                      int        newspec = $1 | $2;
> > >  
> > >                      /* special message for this case */
> > > -                    if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE |
CAS_INITIALLY_DEFERRED))
> > > +                    if ((newspec & CAS_NOT_DEFERRABLE) &&
> > > +                        (newspec & (CAS_INITIALLY_DEFERRED | CAS_ALWAYS_DEFERRED)))
> > >                          ereport(ERROR,
> > >                                  (errcode(ERRCODE_SYNTAX_ERROR),
> > >                                   errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
> > >                                   parser_errposition(@2)));
> > >                      /* generic message for other conflicts */
> > > +                    if ((newspec & CAS_ALWAYS_DEFERRED) &&
> > > +                        (newspec & (CAS_INITIALLY_IMMEDIATE)))
> > > +                        ereport(ERROR,
> > > +                                (errcode(ERRCODE_SYNTAX_ERROR),
> > > +                                 errmsg("conflicting constraint properties 1"),
> > > +                                 parser_errposition(@2)));
> > >                      if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE |
CAS_DEFERRABLE)||
 
> > >                          (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) ==
(CAS_INITIALLY_IMMEDIATE| CAS_INITIALLY_DEFERRED))
 
> > >                          ereport(ERROR,
> > >                                  (errcode(ERRCODE_SYNTAX_ERROR),
> > > -                                 errmsg("conflicting constraint properties"),
> > > +                                 errmsg("conflicting constraint properties 2"),
> > 
> > I'd prefer you just repeat the message (or make them more situationally
> > descriptive), rather than appending a number.  (Repeating error messages
> > is in keeping with the style here.)
> 
> Oy, I forgot about these.  The number was a bread crumb I forgot to
> cleanup :(  So sorry about that.

So, I'm tempted not to add new messages that will require translation,
leaving these as "conflicting constraint properties".

But I'm perfectly happy to make these more informative too if that's
desired.  I just don't know what the expectations are regarding message
catalog translation.  Any advice?

Nico
-- 


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Nico Williams
Date:
Attached is an additional patch, as well as a new, rebased patch.

This includes changes responsive to Álvaro Herrera's commentary about
the SET CONSTRAINTS manual page.

Nico
--

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Robbie Harwood
Date:
Nico Williams <nico@cryptonector.com> writes:

> Attached is an additional patch, as well as a new, rebased patch.
>
> This includes changes responsive to Álvaro Herrera's commentary about
> the SET CONSTRAINTS manual page.

This patch looks good to me.  +1; Álvaro, please update the CF entry
when you're also satisfied.

Thanks,
--Robbie

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Michael Paquier
Date:
On Thu, Jul 12, 2018 at 03:07:33PM -0400, Robbie Harwood wrote:
> This patch looks good to me.  +1; Álvaro, please update the CF entry
> when you're also satisfied.

The patch set does not apply anymore, so I have moved it to next CF,
waiting on author.
--
Michael

Attachment

Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Dmitry Dolgov
Date:
> On Tue, Oct 2, 2018 at 7:43 AM Michael Paquier <michael@paquier.xyz> wrote:
>
> On Thu, Jul 12, 2018 at 03:07:33PM -0400, Robbie Harwood wrote:
> > This patch looks good to me.  +1; Álvaro, please update the CF entry
> > when you're also satisfied.
>
> The patch set does not apply anymore, so I have moved it to next CF,
> waiting on author.

Nothing was changed since then. Since the patch got some interest I'm moving it
to the next CF, but please post the rebased version.


Re: [HACKERS] [PATCH] WIP Add ALWAYS DEFERRED option for constraints

From
Andres Freund
Date:
Hi,

On 2018-11-29 19:04:24 +0100, Dmitry Dolgov wrote:
> > On Tue, Oct 2, 2018 at 7:43 AM Michael Paquier <michael@paquier.xyz> wrote:
> >
> > On Thu, Jul 12, 2018 at 03:07:33PM -0400, Robbie Harwood wrote:
> > > This patch looks good to me.  +1; Álvaro, please update the CF entry
> > > when you're also satisfied.
> >
> > The patch set does not apply anymore, so I have moved it to next CF,
> > waiting on author.
> 
> Nothing was changed since then. Since the patch got some interest I'm moving it
> to the next CF, but please post the rebased version.

Since this hasn't happened yet, I'm going to mark it as returned with
feedback.

Greetings,

Andres Freund