Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator

Lists: pgsql-hackers
From: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Cc: Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-26 15:46:13
Message-ID: A0DF8607-A1A1-40CE-B152-82FC91EF8A3A@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Hello, hackers!

As was mentioned in that message [1], and earlier in [2], DROPping OPERATOR with
negator or commutator doesn't update respective fields (oprnegate and oprcom) on
them. While this issue is probably not very frequent, this behaviour leaves
database in inconsistent state and prevents from using former negator or
commutator.

Proposed patch fixes unwanted behaviour by reseting oprnegate and oprcom fields
to InvalidOid when deleting operator. Code updates tries to update other
operators only if necessary, and only if negator or commutator have target oid
in their respective fields.

To implement desired behaviour with as little code as possible, OperatorUpd
function is extended to accept additional parameter and made externally visible.
It's used from RemoveOperatorById, after checking that update is indeed needed.

Regression tests are added to check DROP OPERATOR behaves as intended (including
case with self-commutator and unlikely case with operator being both negator and
commutator).

Should this patch be added to CommitFest?

[1] — http://www.postgresql.org/message-id/CA+TgmoYThtZZf6yhnq22SZPw7OTiT68iu9wvvidb2Jz50KdAnQ@mail.gmail.com
[2] — http://www.postgresql.org/message-id/15208.1285772173@sss.pgh.pa.us

Cheers,
Roma

Attachment Content-Type Size
fix_drop_operator_reset_oprcom_and_oprnegate_fields_v1.patch application/octet-stream 17.4 KB

From: Euler Taveira <euler(at)timbira(dot)com(dot)br>
To: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>, pgsql-hackers(at)postgresql(dot)org
Cc: Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-26 18:58:31
Message-ID: 56D0A057.7070002@timbira.com.br
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On 26-02-2016 12:46, Roma Sokolov wrote:
> Regression tests are added to check DROP OPERATOR behaves as intended (including
> case with self-commutator and unlikely case with operator being both negator and
> commutator).
>
I don't think those are mandatory.

> Should this patch be added to CommitFest?
>
Why not?

I didn't test your patch but

+ if (isDelete ? (t->oprcom == baseId || t->oprnegate == baseId)
+ : !OidIsValid(t->oprcom) || !OidIsValid(t->oprnegate))

... is hard to understand. Instead, you could separate the conditional
expression into a variable.

+ if (isDelete ? t->oprnegate == baseId : !OidIsValid(t->oprnegate))

It could be separate into a variable to be readable (or at least deserve
a comment).

(isDelete ? InvalidOid : ObjectIdGetDatum(baseId))

... and this one too. It is used in 4 places in that function.

--
Euler Taveira Timbira - http://www.timbira.com.br/
PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento


From: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>
To: Euler Taveira <euler(at)timbira(dot)com(dot)br>
Cc: pgsql-hackers(at)postgresql(dot)org, Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-26 20:51:03
Message-ID: F91420DD-0209-44EA-AB37-B22F641EC943@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Thanks for comments, Euler!

> ... is hard to understand. Instead, you could separate the conditional
> expression into a variable.

Fixed the patch to be more descriptive and to avoid repeating same
computation over and over again. See v2 of the patch attached.

> I don't think those are mandatory.

Why do you think that? Should I remove them or maybe send as separate
patch?

Cheers,
Roma

Attachment Content-Type Size
fix_drop_operator_reset_oprcom_and_oprnegate_fields_v2.patch application/octet-stream 17.7 KB

From: Euler Taveira <euler(at)timbira(dot)com(dot)br>
To: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org, Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-27 00:46:21
Message-ID: 56D0F1DD.8000808@timbira.com.br
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On 26-02-2016 17:51, Roma Sokolov wrote:
> Fixed the patch to be more descriptive and to avoid repeating same
> computation over and over again. See v2 of the patch attached.
>
Oh, much better.

> Why do you think that? Should I remove them or maybe send as separate
> patch?
>
Because it is not a common practice to test catalog dependency on
separate tests (AFAICS initial catalogs are tested with oidjoins.sql).
Also, your test case is too huge for such a small use case. If you can
reduce it to a small set of commands using some of the oidjoins.sql
queries, I think it could be sufficient.

--
Euler Taveira Timbira - http://www.timbira.com.br/
PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento


From: Michael Paquier <michael(dot)paquier(at)gmail(dot)com>
To: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>
Cc: PostgreSQL mailing lists <pgsql-hackers(at)postgresql(dot)org>, Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-27 13:11:05
Message-ID: CAB7nPqQD9sk10o-3euH6H0RVd3dJ6V9ZNykEouHkwhJ26c0kXw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Feb 27, 2016 at 12:46 AM, Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com> wrote:
> Should this patch be added to CommitFest?

Yes please.
--
Michael


From: Yury Zhuravlev <u(dot)zhuravlev(at)postgrespro(dot)ru>
To: <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-02-27 18:59:29
Message-ID: 8d4eaf35-091c-4171-84fb-e67283f4848f@postgrespro.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Roma Sokolov wrote:
> See v2 of the patch attached.

Hello.
I have a stylistic comments. Sometimes you forget a space:
+ replaces[Anum_pg_operator_oprcom - 1] =true;

or use tab insted space:
+ if (OidIsValid(op->oprnegate) ||
+ (OidIsValid(op->oprcom) && operOid != op->oprcom))
+ OperatorUpd(operOid,
+ operOid == op->oprcom ? InvalidOid : op->oprcom,
+ op->oprnegate,
+ true);

And I think if you make this logic into a separate function,
it is possible to simplify the code. OperatorUpd function is too complex.

Also better to add comments to the tests.
The rest seems good.

PS I here thought it would be possible to print operators that have been
changed?

--
Yury Zhuravlev
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company


From: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>
To: Euler Taveira <euler(at)timbira(dot)com(dot)br>
Cc: pgsql-hackers(at)postgresql(dot)org, Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-03-01 16:08:46
Message-ID: BF79B347-E974-4FF8-843D-9FBD68596F35@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> On 27 Feb 2016, at 03:46, Euler Taveira <euler(at)timbira(dot)com(dot)br> wrote:
> Because it is not a common practice to test catalog dependency on
> separate tests (AFAICS initial catalogs are tested with oidjoins.sql).
> Also, your test case is too huge for such a small use case.

It seems oidjoins.sql is automatically generated and contains tests only for
initial database state. On the other hand, there are tests for CREATE OPERATOR
and ALTER OPERATOR, so it seems reasonable to me to have separate DROP OPERATOR
test, or to move all operator related testing to one file. This is however
clearly outside of the scope of this patch, so in v3 I've simplified tests using
queries from oidjoins.sql.

Cheers,
Roma

Attachment Content-Type Size
fix_drop_operator_reset_oprcom_and_oprnegate_fields_v3.patch application/octet-stream 12.2 KB
unknown_filename text/plain 2 bytes

From: David Steele <david(at)pgmasters(dot)net>
To: kgrittn(at)gmail(dot)com
Cc: Roma Sokolov <sokolov(dot)r(dot)v(at)gmail(dot)com>, Euler Taveira <euler(at)timbira(dot)com(dot)br>, pgsql-hackers(at)postgresql(dot)org, Женя Зайцев <zevlg(at)yandex(dot)ru>
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-03-15 18:00:50
Message-ID: 56E84DD2.5040904@pgmasters.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Hi Kevin,

On 3/1/16 11:08 AM, Roma Sokolov wrote:
>> On 27 Feb 2016, at 03:46, Euler Taveira <euler(at)timbira(dot)com(dot)br> wrote:
>> Because it is not a common practice to test catalog dependency on
>> separate tests (AFAICS initial catalogs are tested with oidjoins.sql).
>> Also, your test case is too huge for such a small use case.
>
> It seems oidjoins.sql is automatically generated and contains tests only for
> initial database state. On the other hand, there are tests for CREATE OPERATOR
> and ALTER OPERATOR, so it seems reasonable to me to have separate DROP OPERATOR
> test, or to move all operator related testing to one file. This is however
> clearly outside of the scope of this patch, so in v3 I've simplified tests using
> queries from oidjoins.sql.

You've signed up to review this patch, do you have an idea of when you
might be able to do the review?

Thanks,
--
-David
david(at)pgmasters(dot)net


From: Tomas Vondra <tomas(dot)vondra(at)2ndquadrant(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Re: [PATCH] fix DROP OPERATOR to reset links to itself on commutator and negator
Date: 2016-03-20 14:32:03
Message-ID: 9d1f82aa-546b-cdaa-5558-82b44cf9c4e6@2ndquadrant.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

On 03/01/2016 05:08 PM, Roma Sokolov wrote:
>> On 27 Feb 2016, at 03:46, Euler Taveira <euler(at)timbira(dot)com(dot)br> wrote:
>> Because it is not a common practice to test catalog dependency on
>> separate tests (AFAICS initial catalogs are tested with oidjoins.sql).
>> Also, your test case is too huge for such a small use case.
>
> It seems oidjoins.sql is automatically generated and contains tests only for
> initial database state. On the other hand, there are tests for CREATE OPERATOR
> and ALTER OPERATOR, so it seems reasonable to me to have separate DROP OPERATOR
> test, or to move all operator related testing to one file. This is however
> clearly outside of the scope of this patch, so in v3 I've simplified tests using
> queries from oidjoins.sql.

I think it's OK to have a separate regression test for this. Clearly
oidjoins is not a good place for such tests, and as you point out there
are already tests for CREATE/ALTER OPERATOR, so it's perfectly natural
to add a new file for DROP OPERATOR. I don't think it contradicts any
common practice, as the existing CREATE/ALTER OPERATOR tests do pretty
much the same thing.

One comment for the tests, though - you're using a mix of tabs and
spaces for indentation, which breaks psql unpredictably (when debugging
and pasting the commands to psql). Which is a bit annoying.

A few more comments:

1) OperatorUpd (pg_operator.c)
------------------------------

/*
* check and update the commutator & negator, if necessary
*
* We need a CommandCounterIncrement here in case of a self-commutator
* operator: we'll need to update the tuple that we just inserted.
*/
if (!isDelete)
CommandCounterIncrement();

This would really deserve an explanation of why we don't need to
increment the command counter for a delete.

/* When deleting, reset other operator field to InvalidOid, otherwise,
* set it to point to operator being updated
*/

This comment is a bit broken - the first line should be just '/*' and
the second line uses spaces instead of a tabulator.

I have to admit I find the existing code a bit convoluted, particularly
the part that deals with the (commId == negId) case. And the patch does
not really improve the situation, quite the contrary.

Perhaps it's time to get rid of this optimization? I mean, how likely it
is to have an operator with the same negator and commutator? And how
often we do DROP OPERATOR? Apparently even the original author doubted
this, according to the comment right in front of the block.

2) operatorcmds.c
------------------

/*
* Reset links on commutator and negator. Only do that if either
* oprcom or oprnegate is set and given operator is not self-commutator.
* For self-commutator with negator prevent meaningful updates of the
* same tuple by sending InvalidOid.
*/
if (OidIsValid(op->oprnegate) ||
(OidIsValid(op->oprcom) && operOid != op->oprcom))
OperatorUpd(operOid,
operOid == op->oprcom ? InvalidOid : op->oprcom,
op->oprnegate,
true);

Firstly, this block contains tabulators within both the comment and the
code (e.g. "is not" or in front of the "&&" operator. That seems a bit
broken, I guess.

Also, maybe I'm missing something obvious, but it's not immediately
obvious to me why we're only checking oprcom and not oprnegate? I.e. why
shouldn't the code be

if (OidIsValid(op->oprnegate) ||
(OidIsValid(op->oprcom) && operOid != op->oprcom) ||
(OidIsValid(op->oprnegate) && operOid != op->oprnegate))
OperatorUpd(operOid,
operOid == op->oprcom ? InvalidOid : op->oprcom,
operOid == op->oprnegate ? InvalidOid : op->oprnegate,
true);

regards

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