*** ./doc/src/sgml/func.sgml.orig Mon May 17 14:00:06 2004 --- ./doc/src/sgml/func.sgml Wed May 19 10:27:17 2004 *************** *** 7554,7559 **** --- 7554,7629 ---- + + + bit_and + + bit_and(expression) + + + smallint, integer, bigint or + bit, + + + same as argument data type. + + the bitwise-and of all non-null input values, or null if empty + + + + + + + bit_or + + bit_or(expression) + + + smallint, integer, bigint or + bit, + + + same as argument data type. + + the bitwise-or of all non-null input values, or null if empty. + + + + + + + bool_and + + bool_and(expression) + + + bool + + + bool + + true if all input values are true, otherwise false. + Also known as bool_and. + + + + + + + bool_or + + bool_or(expression) + + + bool + + + bool + + true if at least one input value is true, otherwise false + + + count(*) bigint *************** *** 7571,7576 **** --- 7641,7664 ---- + + + every + + every(expression) + + + bool + + + bool + + true if all input values are true, otherwise false. + Also known as bool_and. + + + + max(expression) any numeric, string, or date/time type same as argument type *************** *** 7661,7666 **** --- 7749,7777 ---- + + ANY + + + SOME + + + Boolean aggregates bool_and and + bool_or correspond to standard SQL aggregates + every and any or + some. + As for any and some, + it seems that there is an ambiguity built into the standard syntax: + + SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...; + + Here ANY can be considered both as leading + to a subquery or as an aggregate if the select expression returns 1 row. + Thus the standard name cannot be given to these aggregates. + + + + Users accustomed to working with other SQL database management systems may be surprised by the performance characteristics of *** ./src/backend/utils/adt/bool.c.orig Mon May 17 14:00:09 2004 --- ./src/backend/utils/adt/bool.c Wed May 19 10:18:13 2004 *************** *** 248,250 **** --- 248,270 ---- PG_RETURN_BOOL(b); } + + /* + * boolean-and and boolean-or aggregates. + */ + + /* function for standard EVERY aggregate implementation conforming to SQL 2003. + * must be strict. It is also named bool_and for homogeneity. + */ + Datum booland_statefunc(PG_FUNCTION_ARGS) + { + PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1)); + } + + /* function for standard ANY/SOME aggregate conforming to SQL 2003. + * must be strict. The name of the aggregate is bool_or. See the doc. + */ + Datum boolor_statefunc(PG_FUNCTION_ARGS) + { + PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1)); + } *** ./src/include/catalog/catversion.h.orig Mon May 17 14:00:11 2004 --- ./src/include/catalog/catversion.h Wed May 19 10:22:14 2004 *************** *** 53,58 **** */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200405141 #endif --- 53,58 ---- */ /* yyyymmddN */ ! #define CATALOG_VERSION_NO 200405191 #endif *** ./src/include/catalog/pg_aggregate.h.orig Sat Nov 29 23:40:58 2003 --- ./src/include/catalog/pg_aggregate.h Wed May 19 10:19:28 2004 *************** *** 149,154 **** --- 149,169 ---- DATA(insert ( 2158 float8_accum float8_stddev 1022 "{0,0,0}" )); DATA(insert ( 2159 numeric_accum numeric_stddev 1231 "{0,0,0}" )); + /* boolean-and and boolean-or */ + DATA(insert ( 2517 booland_statefunc - 16 _null_ )); + DATA(insert ( 2518 boolor_statefunc - 16 _null_ )); + DATA(insert ( 2519 booland_statefunc - 16 _null_ )); + + /* bitwise integer */ + DATA(insert ( 2535 int2and - 21 _null_ )); + DATA(insert ( 2536 int2or - 21 _null_ )); + DATA(insert ( 2537 int4and - 23 _null_ )); + DATA(insert ( 2538 int4or - 23 _null_ )); + DATA(insert ( 2539 int8and - 20 _null_ )); + DATA(insert ( 2540 int8or - 20 _null_ )); + DATA(insert ( 2541 bitand - 1560 _null_ )); + DATA(insert ( 2542 bitor - 1560 _null_ )); + /* * prototypes for functions in pg_aggregate.c */ *** ./src/include/catalog/pg_proc.h.orig Mon May 17 14:00:12 2004 --- ./src/include/catalog/pg_proc.h Wed May 19 10:21:48 2004 *************** *** 3537,3542 **** --- 3537,3577 ---- DESCR("non-persistent series generator"); + /* boolean aggregates */ + DATA(insert OID = 2515 ( booland_statefunc PGNSP PGUID 12 f f t f i 2 16 "16 16" _null_ booland_statefunc - _null_ )); + DESCR("boolean-and aggregate transition function"); + DATA(insert OID = 2516 ( boolor_statefunc PGNSP PGUID 12 f f t f i 2 16 "16 16" _null_ boolor_statefunc - _null_ )); + DESCR("boolean-or aggregate transition function"); + + DATA(insert OID = 2517 ( bool_and PGNSP PGUID 12 t f f f i 1 16 "16" _null_ aggregate_dummy - _null_ )); + DESCR("boolean-and aggregate"); + /* ANY, SOME? These names conflict with subquery operators. See doc. */ + DATA(insert OID = 2518 ( bool_or PGNSP PGUID 12 t f f f i 1 16 "16" _null_ aggregate_dummy - _null_ )); + DESCR("boolean-or aggregate"); + DATA(insert OID = 2519 ( every PGNSP PGUID 12 t f f f i 1 16 "16" _null_ aggregate_dummy - _null_ )); + DESCR("boolean-and aggregate"); + + /* bitwise integer aggregates */ + DATA(insert OID = 2535 ( bit_and PGNSP PGUID 12 t f f f i 1 21 "21" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-and smallint aggregate"); + DATA(insert OID = 2536 ( bit_or PGNSP PGUID 12 t f f f i 1 21 "21" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-or smallint aggregate"); + + DATA(insert OID = 2537 ( bit_and PGNSP PGUID 12 t f f f i 1 23 "23" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-and integer aggregate"); + DATA(insert OID = 2538 ( bit_or PGNSP PGUID 12 t f f f i 1 23 "23" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-or integer aggregate"); + + DATA(insert OID = 2539 ( bit_and PGNSP PGUID 12 t f f f i 1 20 "20" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-and bigint aggregate"); + DATA(insert OID = 2540 ( bit_or PGNSP PGUID 12 t f f f i 1 20 "20" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-or bigint aggregate"); + + DATA(insert OID = 2541 ( bit_and PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-and bit aggregate"); + DATA(insert OID = 2542 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy - _null_)); + DESCR("bitwise-or bit aggregate"); + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, *** ./src/include/utils/builtins.h.orig Mon May 17 14:00:12 2004 --- ./src/include/utils/builtins.h Wed May 19 10:15:58 2004 *************** *** 68,73 **** --- 68,75 ---- extern Datum isfalse(PG_FUNCTION_ARGS); extern Datum isnottrue(PG_FUNCTION_ARGS); extern Datum isnotfalse(PG_FUNCTION_ARGS); + extern Datum booland_statefunc(PG_FUNCTION_ARGS); + extern Datum boolor_statefunc(PG_FUNCTION_ARGS); /* char.c */ extern Datum charin(PG_FUNCTION_ARGS); *** ./src/test/regress/expected/aggregates.out.orig Sat Jul 19 22:20:52 2003 --- ./src/test/regress/expected/aggregates.out Wed May 19 11:32:46 2004 *************** *** 157,159 **** --- 157,295 ---- having exists (select 1 from onek b where sum(distinct a.four + b.four) = b.four); ERROR: aggregates not allowed in WHERE clause + -- + -- test for bitwise integer aggregates + -- + CREATE TEMPORARY TABLE bitwise_test( + i2 INT2, + i4 INT4, + i8 INT8, + i INTEGER, + x INT2, + y BIT(4) + ); + -- empty case + SELECT + BIT_AND(i2) AS "?", + BIT_OR(i4) AS "?" + FROM bitwise_test; + ? | ? + ---+--- + | + (1 row) + + COPY bitwise_test FROM STDIN NULL 'null'; + SELECT + BIT_AND(i2) AS "1", + BIT_AND(i4) AS "1", + BIT_AND(i8) AS "1", + BIT_AND(i) AS "?", + BIT_AND(x) AS "0", + BIT_AND(y) AS "0100", + BIT_OR(i2) AS "7", + BIT_OR(i4) AS "7", + BIT_OR(i8) AS "7", + BIT_OR(i) AS "?", + BIT_OR(x) AS "7", + BIT_OR(y) AS "1101" + FROM bitwise_test; + 1 | 1 | 1 | ? | 0 | 0100 | 7 | 7 | 7 | ? | 7 | 1101 + ---+---+---+---+---+------+---+---+---+---+---+------ + 1 | 1 | 1 | 1 | 0 | 0100 | 7 | 7 | 7 | 3 | 7 | 1101 + (1 row) + + -- + -- test boolean aggregates + -- + -- first test all possible transition and final states + SELECT + -- boolean and transitions + -- null because strict + booland_statefunc(NULL, NULL) IS NULL AS "t", + booland_statefunc(TRUE, NULL) IS NULL AS "t", + booland_statefunc(FALSE, NULL) IS NULL AS "t", + booland_statefunc(NULL, TRUE) IS NULL AS "t", + booland_statefunc(NULL, FALSE) IS NULL AS "t", + -- and actual computations + booland_statefunc(TRUE, TRUE) AS "t", + NOT booland_statefunc(TRUE, FALSE) AS "t", + NOT booland_statefunc(FALSE, TRUE) AS "t", + NOT booland_statefunc(FALSE, FALSE) AS "t"; + t | t | t | t | t | t | t | t | t + ---+---+---+---+---+---+---+---+--- + t | t | t | t | t | t | t | t | t + (1 row) + + SELECT + -- boolean or transitions + -- null because strict + boolor_statefunc(NULL, NULL) IS NULL AS "t", + boolor_statefunc(TRUE, NULL) IS NULL AS "t", + boolor_statefunc(FALSE, NULL) IS NULL AS "t", + boolor_statefunc(NULL, TRUE) IS NULL AS "t", + boolor_statefunc(NULL, FALSE) IS NULL AS "t", + -- actual computations + boolor_statefunc(TRUE, TRUE) AS "t", + boolor_statefunc(TRUE, FALSE) AS "t", + boolor_statefunc(FALSE, TRUE) AS "t", + NOT boolor_statefunc(FALSE, FALSE) AS "t"; + t | t | t | t | t | t | t | t | t + ---+---+---+---+---+---+---+---+--- + t | t | t | t | t | t | t | t | t + (1 row) + + CREATE TEMPORARY TABLE bool_test( + b1 BOOL, + b2 BOOL, + b3 BOOL, + b4 BOOL); + -- empty case + SELECT + BOOL_AND(b1) AS "n", + BOOL_OR(b3) AS "n" + FROM bool_test; + n | n + ---+--- + | + (1 row) + + COPY bool_test FROM STDIN NULL 'null'; + SELECT + BOOL_AND(b1) AS "f", + BOOL_AND(b2) AS "t", + BOOL_AND(b3) AS "f", + BOOL_AND(b4) AS "n", + BOOL_AND(NOT b2) AS "f", + BOOL_AND(NOT b3) AS "t" + FROM bool_test; + f | t | f | n | f | t + ---+---+---+---+---+--- + f | t | f | | f | t + (1 row) + + SELECT + EVERY(b1) AS "f", + EVERY(b2) AS "t", + EVERY(b3) AS "f", + EVERY(b4) AS "n", + EVERY(NOT b2) AS "f", + EVERY(NOT b3) AS "t" + FROM bool_test; + f | t | f | n | f | t + ---+---+---+---+---+--- + f | t | f | | f | t + (1 row) + + SELECT + BOOL_OR(b1) AS "t", + BOOL_OR(b2) AS "t", + BOOL_OR(b3) AS "f", + BOOL_OR(b4) AS "n", + BOOL_OR(NOT b2) AS "f", + BOOL_OR(NOT b3) AS "t" + FROM bool_test; + t | t | f | n | f | t + ---+---+---+---+---+--- + t | t | f | | f | t + (1 row) + *** ./src/test/regress/sql/aggregates.sql.orig Fri Jun 6 17:04:03 2003 --- ./src/test/regress/sql/aggregates.sql Wed May 19 11:30:31 2004 *************** *** 62,64 **** --- 62,182 ---- group by ten having exists (select 1 from onek b where sum(distinct a.four + b.four) = b.four); + + -- + -- test for bitwise integer aggregates + -- + CREATE TEMPORARY TABLE bitwise_test( + i2 INT2, + i4 INT4, + i8 INT8, + i INTEGER, + x INT2, + y BIT(4) + ); + + -- empty case + SELECT + BIT_AND(i2) AS "?", + BIT_OR(i4) AS "?" + FROM bitwise_test; + + COPY bitwise_test FROM STDIN NULL 'null'; + 1 1 1 1 1 B0101 + 3 3 3 null 2 B0100 + 7 7 7 3 4 B1100 + \. + + SELECT + BIT_AND(i2) AS "1", + BIT_AND(i4) AS "1", + BIT_AND(i8) AS "1", + BIT_AND(i) AS "?", + BIT_AND(x) AS "0", + BIT_AND(y) AS "0100", + + BIT_OR(i2) AS "7", + BIT_OR(i4) AS "7", + BIT_OR(i8) AS "7", + BIT_OR(i) AS "?", + BIT_OR(x) AS "7", + BIT_OR(y) AS "1101" + FROM bitwise_test; + + -- + -- test boolean aggregates + -- + -- first test all possible transition and final states + + SELECT + -- boolean and transitions + -- null because strict + booland_statefunc(NULL, NULL) IS NULL AS "t", + booland_statefunc(TRUE, NULL) IS NULL AS "t", + booland_statefunc(FALSE, NULL) IS NULL AS "t", + booland_statefunc(NULL, TRUE) IS NULL AS "t", + booland_statefunc(NULL, FALSE) IS NULL AS "t", + -- and actual computations + booland_statefunc(TRUE, TRUE) AS "t", + NOT booland_statefunc(TRUE, FALSE) AS "t", + NOT booland_statefunc(FALSE, TRUE) AS "t", + NOT booland_statefunc(FALSE, FALSE) AS "t"; + + SELECT + -- boolean or transitions + -- null because strict + boolor_statefunc(NULL, NULL) IS NULL AS "t", + boolor_statefunc(TRUE, NULL) IS NULL AS "t", + boolor_statefunc(FALSE, NULL) IS NULL AS "t", + boolor_statefunc(NULL, TRUE) IS NULL AS "t", + boolor_statefunc(NULL, FALSE) IS NULL AS "t", + -- actual computations + boolor_statefunc(TRUE, TRUE) AS "t", + boolor_statefunc(TRUE, FALSE) AS "t", + boolor_statefunc(FALSE, TRUE) AS "t", + NOT boolor_statefunc(FALSE, FALSE) AS "t"; + + CREATE TEMPORARY TABLE bool_test( + b1 BOOL, + b2 BOOL, + b3 BOOL, + b4 BOOL); + + -- empty case + SELECT + BOOL_AND(b1) AS "n", + BOOL_OR(b3) AS "n" + FROM bool_test; + + COPY bool_test FROM STDIN NULL 'null'; + TRUE null FALSE null + FALSE TRUE null null + null TRUE FALSE null + \. + + SELECT + BOOL_AND(b1) AS "f", + BOOL_AND(b2) AS "t", + BOOL_AND(b3) AS "f", + BOOL_AND(b4) AS "n", + BOOL_AND(NOT b2) AS "f", + BOOL_AND(NOT b3) AS "t" + FROM bool_test; + + SELECT + EVERY(b1) AS "f", + EVERY(b2) AS "t", + EVERY(b3) AS "f", + EVERY(b4) AS "n", + EVERY(NOT b2) AS "f", + EVERY(NOT b3) AS "t" + FROM bool_test; + + SELECT + BOOL_OR(b1) AS "t", + BOOL_OR(b2) AS "t", + BOOL_OR(b3) AS "f", + BOOL_OR(b4) AS "n", + BOOL_OR(NOT b2) AS "f", + BOOL_OR(NOT b3) AS "t" + FROM bool_test;