Skip site navigation (1) Skip section navigation (2)

Re: [PATCHES] binary operators on integers

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Marko Kreen <marko(at)l-t(dot)ee>
Cc: pgsql-patches(at)postgresql(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: [PATCHES] binary operators on integers
Date: 2001-01-20 18:31:49
Message-ID: 3670.980015509@sss.pgh.pa.us (view raw or flat)
Thread:
Lists: pgsql-hackerspgsql-patches
Marko Kreen <marko(at)l-t(dot)ee> writes:
> I can still reproduce it:
> marko=# SELECT 5 & ~6;
> ERROR:  Unable to identify a right operator '&' for type 'int4'
>         You may need to add parentheses or an explicit cast

Correct, we did not rejigger the operator precedence.

I played around with this a little bit, and find that the attached patch
makes the above case work as desired --- essentially, it changes things
so that
	a_expr Op Op a_expr
will be parsed as
	a_expr Op (Op a_expr)
not
	(a_expr Op) Op a_expr
which is what you get now because Op is marked left-associative.

Now, this is a situation where we can't fix one case without breaking
another, namely the case where you really DID want the first Op to be
parsed as a postfix operator.  Thus the problem moves over to here:

regression=# select 4! ~ 10;
ERROR:  Unable to identify an operator '!' for types 'int4' and 'int4'
        You will have to retype this query using an explicit cast
regression=# select (4!) ~ 10;
 ?column?
----------
 f
(1 row)

whereas this worked without parens in 7.0.

Given the infrequency of use of postfix operators compared to prefix,
I am inclined to think that we should change the grammar to make the
latter easier to use at the expense of the former.  On the other hand,
it seems there's a pretty large risk of backwards-incompatibility here.
Comments?

BTW, the regress tests do not break, so they contain no examples where
it makes a difference.

			regards, tom lane


*** src/backend/parser/gram.y.orig	Sat Jan 20 12:37:52 2001
--- src/backend/parser/gram.y	Sat Jan 20 13:03:17 2001
***************
*** 383,388 ****
--- 383,389 ----
  %nonassoc	OVERLAPS
  %nonassoc	BETWEEN
  %nonassoc	IN
+ %left		POSTFIXOP		/* dummy for postfix Op rules */
  %left		Op				/* multi-character ops and user-defined operators */
  %nonassoc	NOTNULL
  %nonassoc	ISNULL
***************
*** 4312,4320 ****
  				{	$$ = makeA_Expr(OP, "+", NULL, $2); }
  		| '-' a_expr					%prec UMINUS
  				{	$$ = doNegate($2); }
! 		| '%' a_expr
  				{	$$ = makeA_Expr(OP, "%", NULL, $2); }
! 		| '^' a_expr
  				{	$$ = makeA_Expr(OP, "^", NULL, $2); }
  		| a_expr '%'
  				{	$$ = makeA_Expr(OP, "%", $1, NULL); }
--- 4313,4321 ----
  				{	$$ = makeA_Expr(OP, "+", NULL, $2); }
  		| '-' a_expr					%prec UMINUS
  				{	$$ = doNegate($2); }
! 		| '%' a_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, "%", NULL, $2); }
! 		| '^' a_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, "^", NULL, $2); }
  		| a_expr '%'
  				{	$$ = makeA_Expr(OP, "%", $1, NULL); }
***************
*** 4353,4361 ****
  
  		| a_expr Op a_expr
  				{	$$ = makeA_Expr(OP, $2, $1, $3); }
! 		| Op a_expr
  				{	$$ = makeA_Expr(OP, $1, NULL, $2); }
! 		| a_expr Op
  				{	$$ = makeA_Expr(OP, $2, $1, NULL); }
  
  		| a_expr AND a_expr
--- 4354,4362 ----
  
  		| a_expr Op a_expr
  				{	$$ = makeA_Expr(OP, $2, $1, $3); }
! 		| Op a_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, $1, NULL, $2); }
! 		| a_expr Op					%prec POSTFIXOP
  				{	$$ = makeA_Expr(OP, $2, $1, NULL); }
  
  		| a_expr AND a_expr
***************
*** 4560,4568 ****
  				{	$$ = makeA_Expr(OP, "+", NULL, $2); }
  		| '-' b_expr					%prec UMINUS
  				{	$$ = doNegate($2); }
! 		| '%' b_expr
  				{	$$ = makeA_Expr(OP, "%", NULL, $2); }
! 		| '^' b_expr
  				{	$$ = makeA_Expr(OP, "^", NULL, $2); }
  		| b_expr '%'
  				{	$$ = makeA_Expr(OP, "%", $1, NULL); }
--- 4561,4569 ----
  				{	$$ = makeA_Expr(OP, "+", NULL, $2); }
  		| '-' b_expr					%prec UMINUS
  				{	$$ = doNegate($2); }
! 		| '%' b_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, "%", NULL, $2); }
! 		| '^' b_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, "^", NULL, $2); }
  		| b_expr '%'
  				{	$$ = makeA_Expr(OP, "%", $1, NULL); }
***************
*** 4589,4597 ****
  
  		| b_expr Op b_expr
  				{	$$ = makeA_Expr(OP, $2, $1, $3); }
! 		| Op b_expr
  				{	$$ = makeA_Expr(OP, $1, NULL, $2); }
! 		| b_expr Op
  				{	$$ = makeA_Expr(OP, $2, $1, NULL); }
  		;
  
--- 4590,4598 ----
  
  		| b_expr Op b_expr
  				{	$$ = makeA_Expr(OP, $2, $1, $3); }
! 		| Op b_expr					%prec UMINUS
  				{	$$ = makeA_Expr(OP, $1, NULL, $2); }
! 		| b_expr Op					%prec POSTFIXOP
  				{	$$ = makeA_Expr(OP, $2, $1, NULL); }
  		;
  

In response to

Responses

pgsql-hackers by date

Next:From: Peter EisentrautDate: 2001-01-20 18:57:00
Subject: Re: C++ interface build on FreeBSD 4.2 broken?
Previous:From: Peter EisentrautDate: 2001-01-20 18:15:22
Subject: Re: "initdb -t" destroys all databases

pgsql-patches by date

Next:From: Peter EisentrautDate: 2001-01-21 01:00:17
Subject: SQL Guide
Previous:From: Marko KreenDate: 2001-01-20 15:31:28
Subject: Re: binary operators on integers

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group