Re: Precedence of %

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
Cc: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Precedence of %
Date: 2005-06-04 15:31:18
Message-ID: 26635.1117899078@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I wrote:
> Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
>> Does anyone understand why the precedence of % is strange:
>> test=> select -25 % -10;

> It's treating it as ((-25) %) - (10), which is probably not so
> surprising given the relative precedence of % and - ... though
> I have to admit I'm not totally clear why it's not (-(25 %)) - (10)
> instead.

Now that I'm fully awake, that last point is easily explained: the
precedence of unary minus is higher than that of %, which in turn
is higher than that of infix minus. So the choice of (-25) % over
-(25 %) is reasonable and correct. Now when the parser is done with
that, it is on the % with a lookahead of - and has to decide whether
to reduce according to

| a_expr '%'
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, NULL); }

or shift expecting to later reduce by

| a_expr '%' a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "%", $1, $3); }

but the precedence of the '-' token is set up for infix minus so the
choice is to reduce (see the Bison manual).

We could possibly fix this by fooling with the precedence of the
productions for postfix '%', but I'm worried that that would have
unintended side-effects. What I'd like to propose instead is that
we remove prefix and postfix '%' entirely --- and also '^', which
is the only other hard-wired operator that appears in all three
forms in the grammar. There are no actual uses of prefix or postfix
'^' in pg_operator, so that loses us nothing. Prefix and postfix '%'
exist, but only for the float8 datatype, not anything else; and I
can't imagine a good reason to write those rather than trunc() or
round(). (Quick: which is which, and how would you remember?)

round() and trunc() also have the virtue that they already have versions
for type numeric. If we keep the operators then we'll be right back
with the complaint that was lodged the other day about exponentiation,
namely unexpected precision loss for numeric inputs:

regression=# select 12345678901234567890.55 %;
?column?
----------------------
1.23456789012346e+19
(1 row)

regression=# select round(12345678901234567890.55);
round
----------------------
12345678901234567891
(1 row)

Comments?

regards, tom lane

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2005-06-04 15:38:05 Re: Precedence of %
Previous Message Qingqing Zhou 2005-06-04 15:08:32 Do we force dependency?