diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/regress/expected/create_aggregate.out | 91 | ||||
-rw-r--r-- | src/test/regress/expected/opr_sanity.out | 97 | ||||
-rw-r--r-- | src/test/regress/sql/create_aggregate.sql | 85 | ||||
-rw-r--r-- | src/test/regress/sql/opr_sanity.sql | 62 |
4 files changed, 311 insertions, 24 deletions
diff --git a/src/test/regress/expected/create_aggregate.out b/src/test/regress/expected/create_aggregate.out index 66e073d2b7b..dac26982bca 100644 --- a/src/test/regress/expected/create_aggregate.out +++ b/src/test/regress/expected/create_aggregate.out @@ -101,24 +101,93 @@ CREATE AGGREGATE sumdouble (float8) msfunc = float8pl, minvfunc = float8mi ); --- Test aggregate combine function +-- aggregate combine and serialization functions +-- Ensure stype and serialtype can't be the same +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = internal +); +ERROR: aggregate serialization type cannot be "internal" +-- if serialtype is specified we need a serialfunc and deserialfunc +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea +); +ERROR: aggregate serialization function must be specified when serialization type is specified +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize +); +ERROR: aggregate deserialization function must be specified when serialization type is specified +-- serialfunc must have correct parameters +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_deserialize, + deserialfunc = numeric_avg_deserialize +); +ERROR: function numeric_avg_deserialize(internal) does not exist +-- deserialfunc must have correct parameters +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_serialize +); +ERROR: function numeric_avg_serialize(bytea) does not exist +-- ensure return type of serialfunc is checked +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = text, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize +); +ERROR: return type of serialization function numeric_avg_serialize is not text +-- ensure combine function parameters are checked +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize, + combinefunc = int4larger +); +ERROR: function int4larger(internal, internal) does not exist -- ensure create aggregate works. -CREATE AGGREGATE mysum (int) +CREATE AGGREGATE myavg (numeric) ( - stype = int, - sfunc = int4pl, - combinefunc = int4pl + stype = internal, + sfunc = numeric_avg_accum, + finalfunc = numeric_avg, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize, + combinefunc = numeric_avg_combine ); -- Ensure all these functions made it into the catalog -SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype +SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype FROM pg_aggregate -WHERE aggfnoid = 'mysum'::REGPROC; - aggfnoid | aggtransfn | aggcombinefn | aggtranstype -----------+------------+--------------+-------------- - mysum | int4pl | int4pl | 23 +WHERE aggfnoid = 'myavg'::REGPROC; + aggfnoid | aggtransfn | aggcombinefn | aggtranstype | aggserialfn | aggdeserialfn | aggserialtype +----------+-------------------+---------------------+--------------+-----------------------+-------------------------+--------------- + myavg | numeric_avg_accum | numeric_avg_combine | 2281 | numeric_avg_serialize | numeric_avg_deserialize | 17 (1 row) -DROP AGGREGATE mysum (int); +DROP AGGREGATE myavg (numeric); -- invalid: nonstrict inverse with strict forward function CREATE FUNCTION float8mi_n(float8, float8) RETURNS float8 AS $$ SELECT $1 - $2; $$ diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index a8dc0c150f5..b1596401306 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -279,15 +279,21 @@ ORDER BY 1, 2; -- Look for functions that return type "internal" and do not have any -- "internal" argument. Such a function would be a security hole since -- it might be used to call an internal function from an SQL command. --- As of 7.3 this query should find only internal_in. +-- As of 7.3 this query should find internal_in, and as of 9.6 aggregate +-- deserialization will be found too. These should contain a runtime check to +-- ensure they can only be called in an aggregate context. SELECT p1.oid, p1.proname FROM pg_proc as p1 WHERE p1.prorettype = 'internal'::regtype AND NOT 'internal'::regtype = ANY (p1.proargtypes); - oid | proname -------+------------- + oid | proname +------+-------------------------- + 2741 | numeric_avg_deserialize + 3336 | numeric_deserialize + 3340 | numeric_poly_deserialize + 2787 | int8_avg_deserialize 2304 | internal_in -(1 row) +(5 rows) -- Look for functions that return a polymorphic type and do not have any -- polymorphic argument. Calls of such functions would be unresolvable @@ -1528,6 +1534,89 @@ WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; -----+--------- (0 rows) +-- Check that all serial functions have a return type the same as the serial +-- type. +SELECT a.aggserialfn,a.aggserialtype,p.prorettype +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggserialfn = p.oid +WHERE a.aggserialtype <> p.prorettype; + aggserialfn | aggserialtype | prorettype +-------------+---------------+------------ +(0 rows) + +-- Check that all the deserial functions have the same input type as the +-- serialtype +SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0] +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid +WHERE p.proargtypes[0] <> a.aggserialtype; + aggserialfn | aggserialtype | proargtypes +-------------+---------------+------------- +(0 rows) + +-- An aggregate should either have a complete set of serialtype, serial func +-- and deserial func, or none of them. +SELECT aggserialtype,aggserialfn,aggdeserialfn +FROM pg_aggregate +WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0) + AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0); + aggserialtype | aggserialfn | aggdeserialfn +---------------+-------------+--------------- +(0 rows) + +-- Check that all aggregates with serialtypes have internal states. +-- (There's no point in serializing anything apart from internal) +SELECT aggfnoid,aggserialtype,aggtranstype +FROM pg_aggregate +WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype; + aggfnoid | aggserialtype | aggtranstype +----------+---------------+-------------- +(0 rows) + +-- Check that all serial functions are strict. It's wasteful for these to be +-- called with NULL values. +SELECT aggfnoid,aggserialfn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggserialfn = p.oid +WHERE p.proisstrict = false; + aggfnoid | aggserialfn +----------+------------- +(0 rows) + +-- Check that all deserial functions are strict. It's wasteful for these to be +-- called with NULL values. +SELECT aggfnoid,aggdeserialfn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid +WHERE p.proisstrict = false; + aggfnoid | aggdeserialfn +----------+--------------- +(0 rows) + +-- Check that no combine functions with an INTERNAL return type are strict. +SELECT aggfnoid,aggcombinefn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggcombinefn = p.oid +INNER JOIN pg_type t ON a.aggtranstype = t.oid +WHERE t.typname = 'internal' AND p.proisstrict = true; + aggfnoid | aggcombinefn +----------+-------------- +(0 rows) + +-- Check that aggregates which have the same transition function also have +-- the same combine, serialization, and deserialization functions. +SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, + b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn +FROM + pg_aggregate a, pg_aggregate b +WHERE + a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND + (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn + OR a.aggdeserialfn != b.aggdeserialfn); + aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn | aggfnoid | aggcombinefn | aggserialfn | aggdeserialfn +----------+--------------+-------------+---------------+----------+--------------+-------------+--------------- +(0 rows) + -- **************** pg_opfamily **************** -- Look for illegal values in pg_opfamily fields SELECT p1.oid diff --git a/src/test/regress/sql/create_aggregate.sql b/src/test/regress/sql/create_aggregate.sql index dfcbc5a0e8b..a7da31e5943 100644 --- a/src/test/regress/sql/create_aggregate.sql +++ b/src/test/regress/sql/create_aggregate.sql @@ -115,22 +115,91 @@ CREATE AGGREGATE sumdouble (float8) minvfunc = float8mi ); --- Test aggregate combine function +-- aggregate combine and serialization functions + +-- Ensure stype and serialtype can't be the same +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = internal +); + +-- if serialtype is specified we need a serialfunc and deserialfunc +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea +); + +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize +); + +-- serialfunc must have correct parameters +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_deserialize, + deserialfunc = numeric_avg_deserialize +); + +-- deserialfunc must have correct parameters +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_serialize +); + +-- ensure return type of serialfunc is checked +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = text, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize +); + +-- ensure combine function parameters are checked +CREATE AGGREGATE myavg (numeric) +( + stype = internal, + sfunc = numeric_avg_accum, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize, + combinefunc = int4larger +); -- ensure create aggregate works. -CREATE AGGREGATE mysum (int) +CREATE AGGREGATE myavg (numeric) ( - stype = int, - sfunc = int4pl, - combinefunc = int4pl + stype = internal, + sfunc = numeric_avg_accum, + finalfunc = numeric_avg, + serialtype = bytea, + serialfunc = numeric_avg_serialize, + deserialfunc = numeric_avg_deserialize, + combinefunc = numeric_avg_combine ); -- Ensure all these functions made it into the catalog -SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype +SELECT aggfnoid,aggtransfn,aggcombinefn,aggtranstype,aggserialfn,aggdeserialfn,aggserialtype FROM pg_aggregate -WHERE aggfnoid = 'mysum'::REGPROC; +WHERE aggfnoid = 'myavg'::REGPROC; -DROP AGGREGATE mysum (int); +DROP AGGREGATE myavg (numeric); -- invalid: nonstrict inverse with strict forward function diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 6c9784a3872..62c84d035d5 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -228,7 +228,9 @@ ORDER BY 1, 2; -- Look for functions that return type "internal" and do not have any -- "internal" argument. Such a function would be a security hole since -- it might be used to call an internal function from an SQL command. --- As of 7.3 this query should find only internal_in. +-- As of 7.3 this query should find internal_in, and as of 9.6 aggregate +-- deserialization will be found too. These should contain a runtime check to +-- ensure they can only be called in an aggregate context. SELECT p1.oid, p1.proname FROM pg_proc as p1 @@ -1002,6 +1004,64 @@ SELECT p.oid, proname FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; +-- Check that all serial functions have a return type the same as the serial +-- type. +SELECT a.aggserialfn,a.aggserialtype,p.prorettype +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggserialfn = p.oid +WHERE a.aggserialtype <> p.prorettype; + +-- Check that all the deserial functions have the same input type as the +-- serialtype +SELECT a.aggserialfn,a.aggserialtype,p.proargtypes[0] +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid +WHERE p.proargtypes[0] <> a.aggserialtype; + +-- An aggregate should either have a complete set of serialtype, serial func +-- and deserial func, or none of them. +SELECT aggserialtype,aggserialfn,aggdeserialfn +FROM pg_aggregate +WHERE (aggserialtype <> 0 OR aggserialfn <> 0 OR aggdeserialfn <> 0) + AND (aggserialtype = 0 OR aggserialfn = 0 OR aggdeserialfn = 0); + +-- Check that all aggregates with serialtypes have internal states. +-- (There's no point in serializing anything apart from internal) +SELECT aggfnoid,aggserialtype,aggtranstype +FROM pg_aggregate +WHERE aggserialtype <> 0 AND aggtranstype <> 'internal'::regtype; + +-- Check that all serial functions are strict. It's wasteful for these to be +-- called with NULL values. +SELECT aggfnoid,aggserialfn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggserialfn = p.oid +WHERE p.proisstrict = false; + +-- Check that all deserial functions are strict. It's wasteful for these to be +-- called with NULL values. +SELECT aggfnoid,aggdeserialfn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggdeserialfn = p.oid +WHERE p.proisstrict = false; + +-- Check that no combine functions with an INTERNAL return type are strict. +SELECT aggfnoid,aggcombinefn +FROM pg_aggregate a +INNER JOIN pg_proc p ON a.aggcombinefn = p.oid +INNER JOIN pg_type t ON a.aggtranstype = t.oid +WHERE t.typname = 'internal' AND p.proisstrict = true; + +-- Check that aggregates which have the same transition function also have +-- the same combine, serialization, and deserialization functions. +SELECT a.aggfnoid, a.aggcombinefn, a.aggserialfn, a.aggdeserialfn, + b.aggfnoid, b.aggcombinefn, b.aggserialfn, b.aggdeserialfn +FROM + pg_aggregate a, pg_aggregate b +WHERE + a.aggfnoid < b.aggfnoid AND a.aggtransfn = b.aggtransfn AND + (a.aggcombinefn != b.aggcombinefn OR a.aggserialfn != b.aggserialfn + OR a.aggdeserialfn != b.aggdeserialfn); -- **************** pg_opfamily **************** |