Обсуждение: binary operators on integers
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
Вложения
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
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
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/
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
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
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
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); }
;
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
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