Thread: binary operators on integers

binary operators on integers

From
Marko Kreen
Date:
Here is my next take on binary operators for integers.
It implements the following operators for int2/int4/int8:

 ~ - not
 & - and
 ^ - xor
 | - or
 << - shift left
 >> - shift right

Notes:

* My original choice for xor was '#' because the '^' operator conflicts
  with power operator on floats but Tom Lane said:

> Well, you *could* use '^' since there's no definition of it for integer
> operands.  But that would mean that something like '4^2', which was
> formerly implicitly coerced to float and interpreted as floating
> power function, would suddenly mean something different.  Again a
> serious risk of silently breaking applications.  This doesn't apply to
> '|' though, since it has no numeric interpretation at all right now.

  As the bit-string uses '^' too for xor-ing it would be nice to be
  consistent.  I am quite unsure on this matter.  The patch now seems
  otherwise sane to me, this is the only issue left.

* On << and >> the second argument is always int32 as this seems
  to be the 'default' int type in PostgreSQL.

* Oids used are 1874 - 1909.

Comments?

Patch is against current CVS.

--
marko


Attachment

Re: binary operators on integers

From
Bruce Momjian
Date:
Can someone comment on this?



> Here is my next take on binary operators for integers.
> It implements the following operators for int2/int4/int8:
>
>  ~ - not
>  & - and
>  ^ - xor
>  | - or
>  << - shift left
>  >> - shift right
>
> Notes:
>
> * My original choice for xor was '#' because the '^' operator conflicts
>   with power operator on floats but Tom Lane said:
>
> > Well, you *could* use '^' since there's no definition of it for integer
> > operands.  But that would mean that something like '4^2', which was
> > formerly implicitly coerced to float and interpreted as floating
> > power function, would suddenly mean something different.  Again a
> > serious risk of silently breaking applications.  This doesn't apply to
> > '|' though, since it has no numeric interpretation at all right now.
>
>   As the bit-string uses '^' too for xor-ing it would be nice to be
>   consistent.  I am quite unsure on this matter.  The patch now seems
>   otherwise sane to me, this is the only issue left.
>
> * On << and >> the second argument is always int32 as this seems
>   to be the 'default' int type in PostgreSQL.
>
> * Oids used are 1874 - 1909.
>
> Comments?
>
> Patch is against current CVS.
>
> --
> marko
>

[ Attachment, skipping... ]


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: binary operators on integers

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Can someone comment on this?

We were debating what to do about the precedence issues; see
followup messages.  I have no problem with adding functions
like this, just gotta pick the operator names and precedences...

            regards, tom lane

Re: binary operators on integers

From
Peter Eisentraut
Date:
This patch was installed, with xor as "#".  The parser still needs work.
Besides the known issue of "|", this also parses funny:

=> select 5 & ~ 6;
ERROR:  Unable to identify a right operator '&' for type 'int4'


Marko Kreen writes:

> Here is my next take on binary operators for integers.
> It implements the following operators for int2/int4/int8:
>
>  ~ - not
>  & - and
>  ^ - xor
>  | - or
>  << - shift left
>  >> - shift right
>
> Notes:
>
> * My original choice for xor was '#' because the '^' operator conflicts
>   with power operator on floats but Tom Lane said:
>
> > Well, you *could* use '^' since there's no definition of it for integer
> > operands.  But that would mean that something like '4^2', which was
> > formerly implicitly coerced to float and interpreted as floating
> > power function, would suddenly mean something different.  Again a
> > serious risk of silently breaking applications.  This doesn't apply to
> > '|' though, since it has no numeric interpretation at all right now.
>
>   As the bit-string uses '^' too for xor-ing it would be nice to be
>   consistent.  I am quite unsure on this matter.  The patch now seems
>   otherwise sane to me, this is the only issue left.
>
> * On << and >> the second argument is always int32 as this seems
>   to be the 'default' int type in PostgreSQL.
>
> * Oids used are 1874 - 1909.
>
> Comments?
>
> Patch is against current CVS.
>
>

--
Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/


Re: binary operators on integers

From
Marko Kreen
Date:
On Tue, Oct 24, 2000 at 10:23:55PM +0200, Peter Eisentraut wrote:
> This patch was installed, with xor as "#".  The parser still needs work.
> Besides the known issue of "|", this also parses funny:
>
> => select 5 & ~ 6;
> ERROR:  Unable to identify a right operator '&' for type 'int4'

I have known that from the beginning.  On first patch I did not get
it work correctly, so in second patch I disabled all gram.y hack
altogether.  So this patch does not change anything in parser/.
At the moment it should be used:  select 5 & (~ 6);

I can hack the gram.y and scan.l to get those operators to work
but as I saw no consensus has been reached in -hackers whether
and how it should be solved globally?


--
marko


Re: binary operators on integers

From
Bruce Momjian
Date:
Looks like this is fixed:

    test=> select 5 & ~ 6;
    ERROR:  Unable to identify a right operator '&' for type 'int4'
            You may need to add parentheses or an explicit cast
    test=> select 5 & (~ 6);
     ?column?
    ----------
            1
    (1 row)

> This patch was installed, with xor as "#".  The parser still needs work.
> Besides the known issue of "|", this also parses funny:
>
> => select 5 & ~ 6;
> ERROR:  Unable to identify a right operator '&' for type 'int4'
>
>
> Marko Kreen writes:
>
> > Here is my next take on binary operators for integers.
> > It implements the following operators for int2/int4/int8:
> >
> >  ~ - not
> >  & - and
> >  ^ - xor
> >  | - or
> >  << - shift left
> >  >> - shift right
> >
> > Notes:
> >
> > * My original choice for xor was '#' because the '^' operator conflicts
> >   with power operator on floats but Tom Lane said:
> >
> > > Well, you *could* use '^' since there's no definition of it for integer
> > > operands.  But that would mean that something like '4^2', which was
> > > formerly implicitly coerced to float and interpreted as floating
> > > power function, would suddenly mean something different.  Again a
> > > serious risk of silently breaking applications.  This doesn't apply to
> > > '|' though, since it has no numeric interpretation at all right now.
> >
> >   As the bit-string uses '^' too for xor-ing it would be nice to be
> >   consistent.  I am quite unsure on this matter.  The patch now seems
> >   otherwise sane to me, this is the only issue left.
> >
> > * On << and >> the second argument is always int32 as this seems
> >   to be the 'default' int type in PostgreSQL.
> >
> > * Oids used are 1874 - 1909.
> >
> > Comments?
> >
> > Patch is against current CVS.
> >
> >
>
> --
> Peter Eisentraut      peter_e@gmx.net       http://yi.org/peter-e/
>
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: binary operators on integers

From
Marko Kreen
Date:
On Fri, Jan 19, 2001 at 04:30:09PM -0500, Bruce Momjian wrote:
> Looks like this is fixed:
>
>     test=> select 5 & ~ 6;
>     ERROR:  Unable to identify a right operator '&' for type 'int4'
>             You may need to add parentheses or an explicit cast
>     test=> select 5 & (~ 6);
>      ?column?
>     ----------
>             1
>     (1 row)

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


Or did you mean it can be fixed with parenthesis?  That was the
case from the beginning.


>
> > This patch was installed, with xor as "#".  The parser still needs work.
> > Besides the known issue of "|", this also parses funny:
> >
> > => select 5 & ~ 6;
> > ERROR:  Unable to identify a right operator '&' for type 'int4'
> >

--
marko


Re: binary operators on integers

From
Tom Lane
Date:
Marko Kreen <marko@l-t.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); }
          ;


Re: binary operators on integers

From
Marko Kreen
Date:
On Sat, Jan 20, 2001 at 01:31:49PM -0500, Tom Lane wrote:
> 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?

I say, go for it! :) if it matters anything :]

And the backwards incompatibility should be simply mentioned in
release notes.  Only problem is, that this is such a obscure
incompatibility that I am not sure e.g. distro packagers bother
to mention it in new 7.1 install splash-screens.  "If you have
used factorial '!' or start of interval '|' operator in
expressions, note that ..." ?

--
marko


Re: binary operators on integers

From
Tom Lane
Date:
I wrote:
> 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?

I backed away from part of the proposed patch --- changing the
precedence of all the prefix-operator productions to UMINUS would
probably break people's queries.  But I've applied the part that
changes the behavior of a_expr Op Op a_expr.  This will now be
parsed as an infix operator followed by a prefix operator.

            regards, tom lane