Well, I was interested in binary operators on integers and as Peter suggested that I should look into it myself, so I did it. Choice of operators: ~ - not & - and # - xor - I like it :) | - or Things I am unsure of: 1) Precedence. I quite nonscientifically hacked in gram.y, and could not still make it understand expression '5 # ~1' nor the precedence between '&' and '|#'... At the moment all the gram.y changes could be dropped and it works ok, but without operator precedence. Any hints? 2) Choice of oids. I took 1890 - 1913. Should I have taken directly from 1874 upwards, or somewhere else? 3) Choice of operators. As I understand the '^' is taken, I wont get it. Now, in gram.y I found that the '|' is used in weird situations and with weird precedence so maybe I should use something else for OR too? 4) Is anybody else interested? ;) I would like to get comments/further hints on this... -- marko
Index: pgsql/doc/src/sgml/oper.sgml =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/doc/src/sgml/oper.sgml,v retrieving revision 1.18 diff -u -r1.18 oper.sgml --- pgsql/doc/src/sgml/oper.sgml 2000/09/15 20:20:11 1.18 +++ pgsql/doc/src/sgml/oper.sgml 2000/09/20 19:04:44 @@ -493,9 +493,35 @@ <ENTRY>Cube root</ENTRY> <ENTRY>||/ 27.0</ENTRY> </ROW> + <ROW> + <ENTRY> & </ENTRY> + <ENTRY>Binary AND</ENTRY> + <ENTRY>91 & 15</ENTRY> + </ROW> + <ROW> + <ENTRY> | </ENTRY> + <ENTRY>Binary OR</ENTRY> + <ENTRY>32 | 3</ENTRY> + </ROW> + <ROW> + <ENTRY> # </ENTRY> + <ENTRY>Binary XOR</ENTRY> + <ENTRY>15 # 4</ENTRY> + </ROW> + <ROW> + <ENTRY> ~ </ENTRY> + <ENTRY>Binary NOT</ENTRY> + <ENTRY>~ 1</ENTRY> + </ROW> </TBODY> </TGROUP> </TABLE> + <Note> + <Para> + The binary operators work only on fixed-precision integer types, + that is, on the int2, int4 and int8. + </Para> + </Note> </Para> </sect1> Index: pgsql/src/backend/parser/gram.y =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.191 diff -u -r2.191 gram.y --- pgsql/src/backend/parser/gram.y 2000/09/19 18:17:55 2.191 +++ pgsql/src/backend/parser/gram.y 2000/09/20 19:04:57 @@ -374,10 +374,13 @@ %nonassoc ISNULL %nonassoc NULL_P %nonassoc IS +%left '|' +%left '#' +%left '&' %left '+' '-' %left '*' '/' '%' %left '^' -%left '|' /* XXX Should this have such a high priority? */ +/* %left '|' */ /* marko - No: Should this have such a +high priority? */ /* Unary Operators */ %right UMINUS %left '.' @@ -4423,6 +4426,9 @@ | '/' { $$ = "/"; } | '%' { $$ = "%"; } | '^' { $$ = "^"; } + | '~' { $$ = "~"; } + | '&' { $$ = "&"; } + | '#' { $$ = "#"; } | '|' { $$ = "|"; } | '<' { $$ = "<"; } | '>' { $$ = ">"; } @@ -4462,6 +4468,8 @@ { $$ = makeA_Expr(OP, "+", NULL, $2); } | '-' a_expr %prec UMINUS { $$ = doNegate($2); } + | '~' a_expr %prec UMINUS + { $$ = makeA_Expr(OP, "~", NULL, $2); } | '%' a_expr { $$ = makeA_Expr(OP, "%", NULL, $2); } | '^' a_expr @@ -4484,6 +4492,10 @@ { $$ = makeA_Expr(OP, "/", $1, $3); } | a_expr '%' a_expr { $$ = makeA_Expr(OP, "%", $1, $3); } + | a_expr '&' a_expr + { $$ = makeA_Expr(OP, "&", $1, $3); } + | a_expr '#' a_expr + { $$ = makeA_Expr(OP, "#", $1, $3); } | a_expr '^' a_expr { $$ = makeA_Expr(OP, "^", $1, $3); } | a_expr '|' a_expr @@ -4716,6 +4728,8 @@ { $$ = makeA_Expr(OP, "+", NULL, $2); } | '-' b_expr %prec UMINUS { $$ = doNegate($2); } + | '~' b_expr %prec UMINUS + { $$ = makeA_Expr(OP, "~", NULL, $2); } | '%' b_expr { $$ = makeA_Expr(OP, "%", NULL, $2); } | '^' b_expr @@ -4738,6 +4752,10 @@ { $$ = makeA_Expr(OP, "/", $1, $3); } | b_expr '%' b_expr { $$ = makeA_Expr(OP, "%", $1, $3); } + | b_expr '&' b_expr + { $$ = makeA_Expr(OP, "&", $1, $3); } + | b_expr '#' b_expr + { $$ = makeA_Expr(OP, "#", $1, $3); } | b_expr '^' b_expr { $$ = makeA_Expr(OP, "^", $1, $3); } | b_expr '|' b_expr Index: pgsql/src/backend/utils/adt/int.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/adt/int.c,v retrieving revision 1.42 diff -u -r1.42 int.c --- pgsql/src/backend/utils/adt/int.c 2000/08/01 18:29:35 1.42 +++ pgsql/src/backend/utils/adt/int.c 2000/09/20 19:04:58 @@ -843,3 +843,83 @@ PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2); } + +/* Binary arithmetics + * + * int[24]and - returns arg1 & arg2 + * int[24]or - returns arg1 | arg2 + * int[24]xor - returns arg1 ^ arg2 + * int[24]not - returns ~arg1 + */ + +Datum +int4and(PG_FUNCTION_ARGS) +{ + int32 arg1 = PG_GETARG_INT32(0); + int32 arg2 = PG_GETARG_INT32(1); + + PG_RETURN_INT32(arg1 & arg2); +} + +Datum +int4or(PG_FUNCTION_ARGS) +{ + int32 arg1 = PG_GETARG_INT32(0); + int32 arg2 = PG_GETARG_INT32(1); + + PG_RETURN_INT32(arg1 | arg2); +} + +Datum +int4xor(PG_FUNCTION_ARGS) +{ + int32 arg1 = PG_GETARG_INT32(0); + int32 arg2 = PG_GETARG_INT32(1); + + PG_RETURN_INT32(arg1 ^ arg2); +} + +Datum +int4not(PG_FUNCTION_ARGS) +{ + int32 arg1 = PG_GETARG_INT32(0); + + PG_RETURN_INT32(~arg1); +} + +Datum +int2and(PG_FUNCTION_ARGS) +{ + int16 arg1 = PG_GETARG_INT16(0); + int16 arg2 = PG_GETARG_INT16(1); + + PG_RETURN_INT16(arg1 & arg2); +} + +Datum +int2or(PG_FUNCTION_ARGS) +{ + int16 arg1 = PG_GETARG_INT16(0); + int16 arg2 = PG_GETARG_INT16(1); + + PG_RETURN_INT16(arg1 | arg2); +} + +Datum +int2xor(PG_FUNCTION_ARGS) +{ + int16 arg1 = PG_GETARG_INT16(0); + int16 arg2 = PG_GETARG_INT16(1); + + PG_RETURN_INT16(arg1 ^ arg2); +} + +Datum +int2not(PG_FUNCTION_ARGS) +{ + int16 arg1 = PG_GETARG_INT16(0); + + PG_RETURN_INT16(~arg1); +} + + Index: pgsql/src/backend/utils/adt/int8.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/adt/int8.c,v retrieving revision 1.24 diff -u -r1.24 int8.c --- pgsql/src/backend/utils/adt/int8.c 2000/07/28 05:07:41 1.24 +++ pgsql/src/backend/utils/adt/int8.c 2000/09/20 19:04:59 @@ -591,6 +591,48 @@ PG_RETURN_INT64(val1 / val2); } +/* Binary arithmetics + * + * int8and - returns arg1 & arg2 + * int8or - returns arg1 | arg2 + * int8xor - returns arg1 ^ arg2 + * int8not - returns ~arg1 + */ + +Datum +int8and(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + int64 arg2 = PG_GETARG_INT64(1); + + PG_RETURN_INT64(arg1 & arg2); +} + +Datum +int8or(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + int64 arg2 = PG_GETARG_INT64(1); + + PG_RETURN_INT64(arg1 | arg2); +} + +Datum +int8xor(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + int64 arg2 = PG_GETARG_INT64(1); + + PG_RETURN_INT64(arg1 ^ arg2); +} + +Datum +int8not(PG_FUNCTION_ARGS) +{ + int64 arg1 = PG_GETARG_INT64(0); + + PG_RETURN_INT64(~arg1); +} /*---------------------------------------------------------- * Conversion operators. Index: pgsql/src/include/catalog/pg_operator.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/catalog/pg_operator.h,v retrieving revision 1.82 diff -u -r1.82 pg_operator.h --- pgsql/src/include/catalog/pg_operator.h 2000/09/15 18:45:27 1.82 +++ pgsql/src/include/catalog/pg_operator.h 2000/09/20 19:05:03 @@ -754,6 +754,19 @@ DATA(insert OID = 1872 ( "<=" PGUID 0 b t f 20 21 16 1867 1871 0 0 int82le scalarltsel scalarltjoinsel )); DATA(insert OID = 1873 ( ">=" PGUID 0 b t f 20 21 16 1866 1870 0 0 int82ge scalargtsel scalargtjoinsel )); +DATA(insert OID = 1890 ( "&" PGUID 0 b t f 21 21 21 1892 0 0 0 int2and +- - )); +DATA(insert OID = 1891 ( "|" PGUID 0 b t f 21 21 21 1891 0 0 0 int2or - +- )); +DATA(insert OID = 1892 ( "#" PGUID 0 b t f 21 21 21 1890 0 0 0 int2xor +- - )); +DATA(insert OID = 1893 ( "~" PGUID 0 l t f 0 21 21 0 0 0 0 int2not +- - )); +DATA(insert OID = 1894 ( "&" PGUID 0 b t f 23 23 23 1895 0 0 0 int4and +- - )); +DATA(insert OID = 1895 ( "|" PGUID 0 b t f 23 23 23 1894 0 0 0 int4or - +- )); +DATA(insert OID = 1896 ( "#" PGUID 0 b t f 23 23 23 1893 0 0 0 int4xor +- - )); +DATA(insert OID = 1897 ( "~" PGUID 0 l t f 0 23 23 0 0 0 0 int4not +- - )); +DATA(insert OID = 1898 ( "&" PGUID 0 b t f 20 20 20 1898 0 0 0 int8and +- - )); +DATA(insert OID = 1899 ( "|" PGUID 0 b t f 20 20 20 1897 0 0 0 int8or - +- )); +DATA(insert OID = 1900 ( "#" PGUID 0 b t f 20 20 20 1896 0 0 0 int8xor +- - )); +DATA(insert OID = 1901 ( "~" PGUID 0 l t f 0 20 20 0 0 0 0 int8not +- - )); + /* * function prototypes */ Index: pgsql/src/include/catalog/pg_proc.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.167 diff -u -r1.167 pg_proc.h --- pgsql/src/include/catalog/pg_proc.h 2000/09/19 18:18:01 1.167 +++ pgsql/src/include/catalog/pg_proc.h 2000/09/20 19:05:10 @@ -2511,6 +2511,32 @@ DATA(insert OID = 1861 ( int82ge PGUID 12 f t t t 2 f 16 "20 21" 100 0 0 100 int82ge - )); DESCR("greater-than-or-equal"); +DATA(insert OID = 1902 ( int2and PGUID 12 f t t t 2 f 21 "21 21" 100 +0 0 100 int2and - )); +DESCR("binary AND"); +DATA(insert OID = 1903 ( int2or PGUID 12 f t t t 2 f 21 "21 21" 100 +0 0 100 int2or - )); +DESCR("binary OR"); +DATA(insert OID = 1904 ( int2xor PGUID 12 f t t t 2 f 21 "21 21" 100 +0 0 100 int2xor - )); +DESCR("binary XOR"); +DATA(insert OID = 1905 ( int2not PGUID 12 f t t t 1 f 21 "21" 100 0 +0 100 int2not - )); +DESCR("binary NOT"); + +DATA(insert OID = 1906 ( int4and PGUID 12 f t t t 2 f 23 "23 23" 100 +0 0 100 int4and - )); +DESCR("binary AND"); +DATA(insert OID = 1907 ( int4or PGUID 12 f t t t 2 f 23 "23 23" 100 +0 0 100 int4or - )); +DESCR("binary OR"); +DATA(insert OID = 1908 ( int4xor PGUID 12 f t t t 2 f 23 "23 23" 100 +0 0 100 int4xor - )); +DESCR("binary XOR"); +DATA(insert OID = 1909 ( int4not PGUID 12 f t t t 1 f 23 "23" 100 0 +0 100 int4not - )); +DESCR("binary NOT"); + +DATA(insert OID = 1910 ( int8and PGUID 12 f t t t 2 f 20 "20 20" 100 +0 0 100 int8and - )); +DESCR("binary AND"); +DATA(insert OID = 1911 ( int8or PGUID 12 f t t t 2 f 20 "20 20" 100 +0 0 100 int8or - )); +DESCR("binary OR"); +DATA(insert OID = 1912 ( int8xor PGUID 12 f t t t 2 f 20 "20 20" 100 +0 0 100 int8xor - )); +DESCR("binary XOR"); +DATA(insert OID = 1913 ( int8not PGUID 12 f t t t 1 f 20 "20" 100 0 +0 100 int8not - )); +DESCR("binary NOT"); /* * prototypes for functions pg_proc.c Index: pgsql/src/include/utils/builtins.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/utils/builtins.h,v retrieving revision 1.138 diff -u -r1.138 builtins.h --- pgsql/src/include/utils/builtins.h 2000/09/19 18:18:02 1.138 +++ pgsql/src/include/utils/builtins.h 2000/09/20 19:05:12 @@ -127,6 +127,15 @@ extern Datum int4larger(PG_FUNCTION_ARGS); extern Datum int4smaller(PG_FUNCTION_ARGS); +extern Datum int4and(PG_FUNCTION_ARGS); +extern Datum int4or(PG_FUNCTION_ARGS); +extern Datum int4xor(PG_FUNCTION_ARGS); +extern Datum int4not(PG_FUNCTION_ARGS); +extern Datum int2and(PG_FUNCTION_ARGS); +extern Datum int2or(PG_FUNCTION_ARGS); +extern Datum int2xor(PG_FUNCTION_ARGS); +extern Datum int2not(PG_FUNCTION_ARGS); + /* name.c */ extern Datum namein(PG_FUNCTION_ARGS); extern Datum nameout(PG_FUNCTION_ARGS); Index: pgsql/src/include/utils/int8.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/utils/int8.h,v retrieving revision 1.23 diff -u -r1.23 int8.h --- pgsql/src/include/utils/int8.h 2000/07/28 05:07:44 1.23 +++ pgsql/src/include/utils/int8.h 2000/09/20 19:05:12 @@ -76,6 +76,11 @@ extern Datum int8larger(PG_FUNCTION_ARGS); extern Datum int8smaller(PG_FUNCTION_ARGS); +extern Datum int8and(PG_FUNCTION_ARGS); +extern Datum int8or(PG_FUNCTION_ARGS); +extern Datum int8xor(PG_FUNCTION_ARGS); +extern Datum int8not(PG_FUNCTION_ARGS); + extern Datum int84pl(PG_FUNCTION_ARGS); extern Datum int84mi(PG_FUNCTION_ARGS); extern Datum int84mul(PG_FUNCTION_ARGS);