9.5 "chained equality" behavior

Started by Joshua Maalmost 9 years ago6 messagesgeneral
Jump to latest
#1Joshua Ma
josh@benchling.com

Our team is upgrading from 9.4 to 9.5, and we noticed this behavior change:

9.4:
# SELECT true = true = true;
?column?
----------
t
(1 row)

9.5:
# SELECT true = true = true;
ERROR: syntax error at or near "="
LINE 1: SELECT true = true = true;

Now, there's actually a larger problem with this, since it's not actually
chained equality and only looks like it. It looks like 9.4 is evaluating
right-to-left. We're going to fix usages of this to instead do (a = b && a
= c) instead of (a = b = c).

However, I wanted to email in because I couldn't see what in the 9.5
changelog (https://www.postgresql.org/docs/9.6/static/release-9-5.html)
would cause this to syntax error. I'm worried that there are other
incompatibilities that we didn't notice.

Can anyone shed some light?

--
Joshua Ma
Benchling | benchling.com

#2Thomas Kellerer
spam_eater@gmx.net
In reply to: Joshua Ma (#1)
Re: 9.5 "chained equality" behavior

Joshua Ma schrieb am 30.05.2017 um 22:56:

We're going to fix usages of this to
instead do (a = b && a = c) instead of (a = b = c).

That has to be (a = b AND a = c)

The && operator is not valid for booleans

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

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joshua Ma (#1)
Re: 9.5 "chained equality" behavior

Joshua Ma <josh@benchling.com> writes:

Our team is upgrading from 9.4 to 9.5, and we noticed this behavior change:
9.5:
# SELECT true = true = true;
ERROR: syntax error at or near "="
LINE 1: SELECT true = true = true;

Now, there's actually a larger problem with this, since it's not actually
chained equality and only looks like it. It looks like 9.4 is evaluating
right-to-left. We're going to fix usages of this to instead do (a = b && a
= c) instead of (a = b = c).

However, I wanted to email in because I couldn't see what in the 9.5
changelog (https://www.postgresql.org/docs/9.6/static/release-9-5.html)
would cause this to syntax error.

This is a consequence of commit c6b3c939b "Make operator precedence follow
the SQL standard more closely", which removed the former "%right '='"
grammar declaration. That caused "a = b = c" to be parsed as "a = (b = c)",
which was surprising, and wouldn't work at all unless a was boolean.
Now "=" is declared %nonassoc, so that if you actually want behavior like
that, you need to write some parens. But it seems much more likely that
people writing that are making a mistake.

We discussed the associativity-of-= issue in the thread leading up to
that patch,
/messages/by-id/12603.1424360914@sss.pgh.pa.us
but I evidently forgot to mention this detail in the commit log message,
so it didn't get into the release notes either.

regards, tom lane

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

#4David G. Johnston
david.g.johnston@gmail.com
In reply to: Joshua Ma (#1)
Re: 9.5 "chained equality" behavior

On Tue, May 30, 2017 at 1:56 PM, Joshua Ma <josh@benchling.com> wrote:

Our team is upgrading from 9.4 to 9.5, and we noticed this behavior change:

9.4:
# SELECT true = true = true;
?column?
----------
t
(1 row)

9.5:
# SELECT true = true = true;
ERROR: syntax error at or near "="
LINE 1: SELECT true = true = true;

Now, there's actually a larger problem with this, since it's not actually
chained equality and only looks like it.

I'm not understanding what the larger problem is here.​

It looks like 9.4 is evaluating right-to-left.

Its documented​ as such.

We're going to fix usages of this to instead do (a = b && a = c) instead of

(a = b = c).

​As noted by Thomas, AND, not &&

However, I wanted to email in because I couldn't see what in the 9.5
changelog (https://www.postgresql.org/docs/9.6/static/release-9-5.html)
would cause this to syntax error. I'm worried that there are other
incompatibilities that we didn't notice.

​The first bullet item could be construed to cover this particular
​behavior change:

* Adjust operator precedence to match the SQL standard (Tom Lane)

The commit behind that release note doesn't mention this particular
behavior change explicitly though.

The documentation change was done correctly. Prior to 9.5 "=" was its own
group and had right associativity just as you observe. In 9.5 it moved to
the comparison operators section which don't have associativity - namely
because aside from equality all of the comparison operators convert their
inputs to a boolean and so cannot be placed in sequence like shown here
(boolean compared to, say, integer doesn't work). Boolean equality is the
one exception which is what no longer works - so the docs are correct.

I suspect the answer is that the current behavior is intentional and has
some support in either consistency or the SQL standard.

David J.

#5David G. Johnston
david.g.johnston@gmail.com
In reply to: David G. Johnston (#4)
Re: 9.5 "chained equality" behavior

On Tue, May 30, 2017 at 2:32 PM, David G. Johnston <
david.g.johnston@gmail.com> wrote:

​...​
namely because aside from equality all of the comparison operators
convert their inputs to a boolean and so cannot be placed in sequence like
shown here (boolean compared to, say, integer doesn't work). Boolean
equality is the one exception which is what no longer works - so the docs
are correct.

​Yes, that was poorly written...booleans keep the same type and so can be
"chained" while other types do not. But precedence is not based upon type,
just the operator.

David J.​

#6Alban Hertroys
haramrae@gmail.com
In reply to: Joshua Ma (#1)
Re: 9.5 "chained equality" behavior

On 30 May 2017, at 22:56, Joshua Ma <josh@benchling.com> wrote:

Our team is upgrading from 9.4 to 9.5, and we noticed this behavior change:

9.4:
# SELECT true = true = true;
?column?
----------
t
(1 row)

Does that really do what you intended though?

# select false = false = false;
?column?
----------
f
(1 row)

I suspect you expect that to result in 't', not 'f', so replacing that with AND would change the behaviour for false boolean values. (This is from 9.3, btw)

Perhaps explicitly adding the braces that pre-9.5 pg adds implicitly gets you what you had? I suspect that would work on 9.5 as well (but can't test right now).

# select false = (false = false);
?column?
----------
f
(1 row)

# select true = (true = true);
?column?
----------
t
(1 row)

Alban Hertroys
--
If you can't see the forest for the trees,
cut the trees and you'll find there is no forest.

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