aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/create_aggregate.out91
-rw-r--r--src/test/regress/expected/opr_sanity.out97
-rw-r--r--src/test/regress/sql/create_aggregate.sql85
-rw-r--r--src/test/regress/sql/opr_sanity.sql62
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 ****************