1998-10-29 05:25:23 +01:00
|
|
|
--
|
2000-01-05 07:07:58 +01:00
|
|
|
-- OPR_SANITY
|
1999-03-28 04:07:58 +02:00
|
|
|
-- Sanity checks for common errors in making operator/procedure system tables:
|
2016-01-05 21:00:54 +01:00
|
|
|
-- pg_operator, pg_proc, pg_cast, pg_conversion, pg_aggregate, pg_am,
|
2015-05-19 17:47:42 +02:00
|
|
|
-- pg_amop, pg_amproc, pg_opclass, pg_opfamily, pg_index.
|
1999-03-28 04:07:58 +02:00
|
|
|
--
|
2014-08-16 19:22:52 +02:00
|
|
|
-- Every test failure in this file should be closely inspected.
|
|
|
|
-- The description of the failing test should be read carefully before
|
|
|
|
-- adjusting the expected output. In most cases, the queries should
|
|
|
|
-- not find *any* matching entries.
|
1999-03-28 04:07:58 +02:00
|
|
|
--
|
|
|
|
-- NB: we assume the oidjoins test will have caught any dangling links,
|
|
|
|
-- that is OID or REGPROC fields that are not zero and do not match some
|
|
|
|
-- row in the linked-to table. However, if we want to enforce that a link
|
|
|
|
-- field can't be 0, we have to check it here.
|
1998-10-29 05:25:23 +01:00
|
|
|
--
|
|
|
|
-- NB: run this test earlier than the create_operator test, because
|
|
|
|
-- that test creates some bogus operators...
|
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
|
|
|
|
-- Helper functions to deal with cases where binary-coercible matches are
|
|
|
|
-- allowed.
|
|
|
|
|
|
|
|
-- This should match IsBinaryCoercible() in parse_coerce.c.
|
2006-09-10 02:29:35 +02:00
|
|
|
create function binary_coercible(oid, oid) returns bool as $$
|
|
|
|
SELECT ($1 = $2) OR
|
|
|
|
EXISTS(select 1 from pg_catalog.pg_cast where
|
2003-05-26 02:11:29 +02:00
|
|
|
castsource = $1 and casttarget = $2 and
|
2008-10-31 09:39:22 +01:00
|
|
|
castmethod = 'b' and castcontext = 'i') OR
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
($2 = 'pg_catalog.any'::pg_catalog.regtype) OR
|
2006-09-10 02:29:35 +02:00
|
|
|
($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
|
|
|
|
EXISTS(select 1 from pg_catalog.pg_type where
|
2015-05-19 17:47:42 +02:00
|
|
|
oid = $1 and typelem != 0 and typlen = -1)) OR
|
|
|
|
($2 = 'pg_catalog.anyrange'::pg_catalog.regtype AND
|
|
|
|
(select typtype from pg_catalog.pg_type where oid = $1) = 'r')
|
2006-09-10 02:29:35 +02:00
|
|
|
$$ language sql strict stable;
|
2003-05-26 02:11:29 +02:00
|
|
|
|
|
|
|
-- This one ignores castcontext, so it considers only physical equivalence
|
|
|
|
-- and not whether the coercion can be invoked implicitly.
|
2006-09-10 02:29:35 +02:00
|
|
|
create function physically_coercible(oid, oid) returns bool as $$
|
|
|
|
SELECT ($1 = $2) OR
|
|
|
|
EXISTS(select 1 from pg_catalog.pg_cast where
|
2003-05-26 02:11:29 +02:00
|
|
|
castsource = $1 and casttarget = $2 and
|
2008-10-31 09:39:22 +01:00
|
|
|
castmethod = 'b') OR
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
($2 = 'pg_catalog.any'::pg_catalog.regtype) OR
|
2006-09-10 02:29:35 +02:00
|
|
|
($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
|
|
|
|
EXISTS(select 1 from pg_catalog.pg_type where
|
2015-05-19 17:47:42 +02:00
|
|
|
oid = $1 and typelem != 0 and typlen = -1)) OR
|
|
|
|
($2 = 'pg_catalog.anyrange'::pg_catalog.regtype AND
|
|
|
|
(select typtype from pg_catalog.pg_type where oid = $1) = 'r')
|
2006-09-10 02:29:35 +02:00
|
|
|
$$ language sql strict stable;
|
2003-05-26 02:11:29 +02:00
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- **************** pg_proc ****************
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- Look for illegal values in pg_proc fields.
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
2002-08-22 02:01:51 +02:00
|
|
|
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
|
2005-03-29 02:17:27 +02:00
|
|
|
p1.pronargs < 0 OR
|
2008-12-18 19:20:35 +01:00
|
|
|
p1.pronargdefaults < 0 OR
|
|
|
|
p1.pronargdefaults > p1.pronargs OR
|
2005-03-29 02:17:27 +02:00
|
|
|
array_lower(p1.proargtypes, 1) != 0 OR
|
|
|
|
array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
|
2007-01-22 02:35:23 +01:00
|
|
|
0::oid = ANY (p1.proargtypes) OR
|
|
|
|
procost <= 0 OR
|
2016-01-09 23:20:58 +01:00
|
|
|
CASE WHEN proretset THEN prorows <= 0 ELSE prorows != 0 END OR
|
|
|
|
provolatile NOT IN ('i', 's', 'v') OR
|
|
|
|
proparallel NOT IN ('s', 'r', 'u');
|
1998-10-29 05:25:23 +01:00
|
|
|
|
2008-07-16 18:55:24 +02:00
|
|
|
-- prosrc should never be null or empty
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-';
|
|
|
|
|
2008-12-19 19:25:20 +01:00
|
|
|
-- proiswindow shouldn't be set together with proisagg or proretset
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc AS p1
|
|
|
|
WHERE proiswindow AND (proisagg OR proretset);
|
|
|
|
|
2008-12-04 18:51:28 +01:00
|
|
|
-- pronargdefaults should be 0 iff proargdefaults is null
|
2008-12-18 19:20:35 +01:00
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc AS p1
|
|
|
|
WHERE (pronargdefaults <> 0) != (proargdefaults IS NOT NULL);
|
2008-12-04 18:51:28 +01:00
|
|
|
|
2008-07-16 18:55:24 +02:00
|
|
|
-- probin should be non-empty for C functions, null everywhere else
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE prolang = 13 AND (probin IS NULL OR probin = '' OR probin = '-');
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE prolang != 13 AND probin IS NOT NULL;
|
|
|
|
|
1999-03-29 03:30:45 +02:00
|
|
|
-- Look for conflicting proc definitions (same names and input datatypes).
|
2000-06-19 05:55:01 +02:00
|
|
|
-- (This test should be dead code now that we have the unique index
|
2006-07-27 21:52:07 +02:00
|
|
|
-- pg_proc_proname_args_nsp_index, but I'll leave it in anyway.)
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname, p2.oid, p2.proname
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
|
|
|
p1.proname = p2.proname AND
|
|
|
|
p1.pronargs = p2.pronargs AND
|
|
|
|
p1.proargtypes = p2.proargtypes;
|
|
|
|
|
2002-04-11 22:00:18 +02:00
|
|
|
-- Considering only built-in procs (prolang = 12), look for multiple uses
|
1999-03-29 03:30:45 +02:00
|
|
|
-- of the same internal function (ie, matching prosrc fields). It's OK to
|
|
|
|
-- have several entries with different pronames for the same internal function,
|
|
|
|
-- but conflicts in the number of arguments and other critical items should
|
2006-07-28 20:33:04 +02:00
|
|
|
-- be complained of. (We don't check data types here; see next query.)
|
|
|
|
-- Note: ignore aggregate functions here, since they all point to the same
|
|
|
|
-- dummy built-in function.
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname, p2.oid, p2.proname
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
2006-07-27 21:52:07 +02:00
|
|
|
WHERE p1.oid < p2.oid AND
|
2006-12-24 01:29:20 +01:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
2006-07-28 20:33:04 +02:00
|
|
|
(p1.proisagg = false OR p2.proisagg = false) AND
|
2000-06-19 05:55:01 +02:00
|
|
|
(p1.prolang != p2.prolang OR
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.proisagg != p2.proisagg OR
|
2002-05-18 15:48:01 +02:00
|
|
|
p1.prosecdef != p2.prosecdef OR
|
2015-05-29 19:26:21 +02:00
|
|
|
p1.proleakproof != p2.proleakproof OR
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.proisstrict != p2.proisstrict OR
|
|
|
|
p1.proretset != p2.proretset OR
|
2002-04-05 02:31:36 +02:00
|
|
|
p1.provolatile != p2.provolatile OR
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.pronargs != p2.pronargs);
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
-- Look for uses of different type OIDs in the argument/result type fields
|
|
|
|
-- for different aliases of the same built-in function.
|
2003-04-09 01:20:04 +02:00
|
|
|
-- This indicates that the types are being presumed to be binary-equivalent,
|
|
|
|
-- or that the built-in function is prepared to deal with different types.
|
1999-03-29 03:30:45 +02:00
|
|
|
-- That's not wrong, necessarily, but we make lists of all the types being
|
|
|
|
-- so treated. Note that the expected output of this part of the test will
|
2003-04-09 01:20:04 +02:00
|
|
|
-- need to be modified whenever new pairs of types are made binary-equivalent,
|
|
|
|
-- or when new polymorphic built-in functions are added!
|
2002-04-11 22:00:18 +02:00
|
|
|
-- Note: ignore aggregate functions here, since they all point to the same
|
2011-11-21 22:19:53 +01:00
|
|
|
-- dummy built-in function. Likewise, ignore range constructor functions.
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.prorettype, p2.prorettype
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2011-11-21 22:19:53 +01:00
|
|
|
p1.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
p2.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
(p1.prorettype < p2.prorettype)
|
2008-08-05 04:43:18 +02:00
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2011-11-21 22:19:53 +01:00
|
|
|
p1.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
p2.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
(p1.proargtypes[0] < p2.proargtypes[0])
|
2008-08-05 04:43:18 +02:00
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2011-11-21 22:19:53 +01:00
|
|
|
p1.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
p2.prosrc NOT LIKE E'range\\_constructor_' AND
|
|
|
|
(p1.proargtypes[1] < p2.proargtypes[1])
|
2008-08-05 04:43:18 +02:00
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[2] < p2.proargtypes[2])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[3], p2.proargtypes[3]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[3] < p2.proargtypes[3])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[4], p2.proargtypes[4]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[4] < p2.proargtypes[4])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[5], p2.proargtypes[5]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[5] < p2.proargtypes[5])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[6], p2.proargtypes[6]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[6] < p2.proargtypes[6])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT p1.proargtypes[7], p2.proargtypes[7]
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2000-06-05 09:29:25 +02:00
|
|
|
p1.prosrc = p2.prosrc AND
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.prolang = 12 AND p2.prolang = 12 AND
|
|
|
|
NOT p1.proisagg AND NOT p2.proisagg AND
|
2008-08-05 04:43:18 +02:00
|
|
|
(p1.proargtypes[7] < p2.proargtypes[7])
|
|
|
|
ORDER BY 1, 2;
|
1999-03-29 03:30:45 +02:00
|
|
|
|
2002-08-23 18:41:38 +02:00
|
|
|
-- 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.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE p1.prorettype = 'internal'::regtype AND NOT
|
2005-03-29 02:17:27 +02:00
|
|
|
'internal'::regtype = ANY (p1.proargtypes);
|
2002-08-23 18:41:38 +02:00
|
|
|
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
-- Look for functions that return a polymorphic type and do not have any
|
|
|
|
-- polymorphic argument. Calls of such functions would be unresolvable
|
Fix assorted inconsistencies in GiST opclass support function declarations.
The conventions specified by the GiST SGML documentation were widely
ignored. For example, the strategy-number argument for "consistent" and
"distance" functions is specified to be a smallint, but most of the
built-in support functions declared it as an integer, and for that matter
the core code passed it using Int32GetDatum not Int16GetDatum. None of
that makes any real difference at runtime, but it's quite confusing for
newcomers to the code, and it makes it very hard to write an amvalidate()
function that checks support function signatures. So let's try to instill
some consistency here.
Another similar issue is that the "query" argument is not of a single
well-defined type, but could have different types depending on the strategy
(corresponding to search operators with different righthand-side argument
types). Some of the functions threw up their hands and declared the query
argument as being of "internal" type, which surely isn't right ("any" would
have been more appropriate); but the majority position seemed to be to
declare it as being of the indexed data type, corresponding to a search
operator with both input types the same. So I've specified a convention
that that's what to do always.
Also, the result of the "union" support function actually must be of the
index's storage type, but the documentation suggested declaring it to
return "internal", and some of the functions followed that. Standardize
on telling the truth, instead.
Similarly, standardize on declaring the "same" function's inputs as
being of the storage type, not "internal".
Also, somebody had forgotten to add the "recheck" argument to both
the documentation of the "distance" support function and all of their
SQL declarations, even though the C code was happily using that argument.
Clean that up too.
Fix up some other omissions in the docs too, such as documenting that
union's second input argument is vestigial.
So far as the errors in core function declarations go, we can just fix
pg_proc.h and bump catversion. Adjusting the erroneous declarations in
contrib modules is more debatable: in principle any change in those
scripts should involve an extension version bump, which is a pain.
However, since these changes are purely cosmetic and make no functional
difference, I think we can get away without doing that.
2016-01-19 18:04:32 +01:00
|
|
|
-- at parse time. As of 9.6 this query should find only some input functions
|
|
|
|
-- and GiST support functions associated with these pseudotypes.
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE p1.prorettype IN
|
|
|
|
('anyelement'::regtype, 'anyarray'::regtype, 'anynonarray'::regtype,
|
|
|
|
'anyenum'::regtype, 'anyrange'::regtype)
|
|
|
|
AND NOT
|
|
|
|
('anyelement'::regtype = ANY (p1.proargtypes) OR
|
|
|
|
'anyarray'::regtype = ANY (p1.proargtypes) OR
|
|
|
|
'anynonarray'::regtype = ANY (p1.proargtypes) OR
|
|
|
|
'anyenum'::regtype = ANY (p1.proargtypes) OR
|
|
|
|
'anyrange'::regtype = ANY (p1.proargtypes))
|
|
|
|
ORDER BY 2;
|
|
|
|
|
2016-01-05 21:00:54 +01:00
|
|
|
-- Look for functions that accept cstring and are neither datatype input
|
|
|
|
-- functions nor encoding conversion functions. It's almost never a good
|
|
|
|
-- idea to use cstring input for a function meant to be called from SQL;
|
|
|
|
-- text should be used instead, because cstring lacks suitable casts.
|
|
|
|
-- As of 9.6 this query should find only cstring_out and cstring_send.
|
|
|
|
-- However, we must manually exclude shell_in, which might or might not be
|
|
|
|
-- rejected by the EXISTS clause depending on whether there are currently
|
|
|
|
-- any shell types.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE 'cstring'::regtype = ANY (p1.proargtypes)
|
|
|
|
AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typinput = p1.oid)
|
|
|
|
AND NOT EXISTS(SELECT 1 FROM pg_conversion WHERE conproc = p1.oid)
|
|
|
|
AND p1.oid != 'shell_in(cstring)'::regprocedure
|
|
|
|
ORDER BY 1;
|
|
|
|
|
|
|
|
-- Likewise, look for functions that return cstring and aren't datatype output
|
|
|
|
-- functions nor typmod output functions.
|
|
|
|
-- As of 9.6 this query should find only cstring_in and cstring_recv.
|
|
|
|
-- However, we must manually exclude shell_out.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE p1.prorettype = 'cstring'::regtype
|
|
|
|
AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typoutput = p1.oid)
|
|
|
|
AND NOT EXISTS(SELECT 1 FROM pg_type WHERE typmodout = p1.oid)
|
|
|
|
AND p1.oid != 'shell_out(opaque)'::regprocedure
|
|
|
|
ORDER BY 1;
|
|
|
|
|
2009-11-29 19:53:54 +01:00
|
|
|
-- Check for length inconsistencies between the various argument-info arrays.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proallargtypes IS NOT NULL AND
|
|
|
|
array_length(proallargtypes,1) < array_length(proargtypes,1);
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proargmodes IS NOT NULL AND
|
|
|
|
array_length(proargmodes,1) < array_length(proargtypes,1);
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proargnames IS NOT NULL AND
|
|
|
|
array_length(proargnames,1) < array_length(proargtypes,1);
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proallargtypes IS NOT NULL AND proargmodes IS NOT NULL AND
|
|
|
|
array_length(proallargtypes,1) <> array_length(proargmodes,1);
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proallargtypes IS NOT NULL AND proargnames IS NOT NULL AND
|
|
|
|
array_length(proallargtypes,1) <> array_length(proargnames,1);
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proargmodes IS NOT NULL AND proargnames IS NOT NULL AND
|
|
|
|
array_length(proargmodes,1) <> array_length(proargnames,1);
|
|
|
|
|
2014-04-24 03:21:05 +02:00
|
|
|
-- Check that proallargtypes matches proargtypes
|
|
|
|
SELECT p1.oid, p1.proname, p1.proargtypes, p1.proallargtypes, p1.proargmodes
|
|
|
|
FROM pg_proc as p1
|
|
|
|
WHERE proallargtypes IS NOT NULL AND
|
|
|
|
ARRAY(SELECT unnest(proargtypes)) <>
|
|
|
|
ARRAY(SELECT proallargtypes[i]
|
|
|
|
FROM generate_series(1, array_length(proallargtypes, 1)) g(i)
|
|
|
|
WHERE proargmodes IS NULL OR proargmodes[i] IN ('i', 'b', 'v'));
|
|
|
|
|
2012-03-23 22:29:57 +01:00
|
|
|
-- Check for protransform functions with the wrong signature
|
|
|
|
SELECT p1.oid, p1.proname, p2.oid, p2.proname
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p2.oid = p1.protransform AND
|
|
|
|
(p2.prorettype != 'internal'::regtype OR p2.proretset OR p2.pronargs != 1
|
|
|
|
OR p2.proargtypes[0] != 'internal'::regtype);
|
|
|
|
|
2011-03-03 07:33:19 +01:00
|
|
|
-- Insist that all built-in pg_proc entries have descriptions
|
|
|
|
SELECT p1.oid, p1.proname
|
|
|
|
FROM pg_proc as p1 LEFT JOIN pg_description as d
|
|
|
|
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
|
|
|
|
WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
|
|
|
|
2014-06-05 13:54:16 +02:00
|
|
|
-- List of built-in leakproof functions
|
|
|
|
--
|
|
|
|
-- Leakproof functions should only be added after carefully
|
|
|
|
-- scrutinizing all possibly executed codepaths for possible
|
|
|
|
-- information leaks. Don't add functions here unless you know what a
|
|
|
|
-- leakproof function is. If unsure, don't mark it as such.
|
|
|
|
|
|
|
|
-- temporarily disable fancy output, so catalog changes create less diff noise
|
|
|
|
\a\t
|
|
|
|
|
|
|
|
SELECT p1.oid::regprocedure
|
|
|
|
FROM pg_proc p1 JOIN pg_namespace pn
|
|
|
|
ON pronamespace = pn.oid
|
|
|
|
WHERE nspname = 'pg_catalog' AND proleakproof
|
|
|
|
ORDER BY 1;
|
|
|
|
|
|
|
|
-- restore normal output mode
|
|
|
|
\a\t
|
|
|
|
|
2014-06-12 21:54:13 +02:00
|
|
|
-- List of functions used by libpq's fe-lobj.c
|
|
|
|
--
|
|
|
|
-- If the output of this query changes, you probably broke libpq.
|
|
|
|
-- lo_initialize() assumes that there will be at most one match for
|
|
|
|
-- each listed name.
|
|
|
|
select proname, oid from pg_catalog.pg_proc
|
|
|
|
where proname in (
|
|
|
|
'lo_open',
|
|
|
|
'lo_close',
|
|
|
|
'lo_creat',
|
|
|
|
'lo_create',
|
|
|
|
'lo_unlink',
|
|
|
|
'lo_lseek',
|
|
|
|
'lo_lseek64',
|
|
|
|
'lo_tell',
|
|
|
|
'lo_tell64',
|
|
|
|
'lo_truncate',
|
|
|
|
'lo_truncate64',
|
|
|
|
'loread',
|
|
|
|
'lowrite')
|
|
|
|
and pronamespace = (select oid from pg_catalog.pg_namespace
|
|
|
|
where nspname = 'pg_catalog')
|
|
|
|
order by 1;
|
|
|
|
|
2002-08-23 18:41:38 +02:00
|
|
|
|
2002-07-19 01:11:32 +02:00
|
|
|
-- **************** pg_cast ****************
|
2002-04-11 22:00:18 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
-- Catch bogus values in pg_cast columns (other than cases detected by
|
|
|
|
-- oidjoins test).
|
2002-07-19 01:11:32 +02:00
|
|
|
|
|
|
|
SELECT *
|
|
|
|
FROM pg_cast c
|
2008-10-31 09:39:22 +01:00
|
|
|
WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i')
|
|
|
|
OR castmethod NOT IN ('f', 'b' ,'i');
|
|
|
|
|
|
|
|
-- Check that castfunc is nonzero only for cast methods that need a function,
|
|
|
|
-- and zero otherwise
|
|
|
|
|
|
|
|
SELECT *
|
|
|
|
FROM pg_cast c
|
|
|
|
WHERE (castmethod = 'f' AND castfunc = 0)
|
|
|
|
OR (castmethod IN ('b', 'i') AND castfunc <> 0);
|
2004-06-16 03:27:00 +02:00
|
|
|
|
|
|
|
-- Look for casts to/from the same type that aren't length coercion functions.
|
|
|
|
-- (We assume they are length coercions if they take multiple arguments.)
|
|
|
|
-- Such entries are not necessarily harmful, but they are useless.
|
|
|
|
|
|
|
|
SELECT *
|
|
|
|
FROM pg_cast c
|
|
|
|
WHERE castsource = casttarget AND castfunc = 0;
|
|
|
|
|
|
|
|
SELECT c.*
|
|
|
|
FROM pg_cast c, pg_proc p
|
|
|
|
WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget;
|
2002-07-19 01:11:32 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
-- Look for cast functions that don't have the right signature. The
|
|
|
|
-- argument and result types in pg_proc must be the same as, or binary
|
|
|
|
-- compatible with, what it says in pg_cast.
|
2004-03-15 02:13:41 +01:00
|
|
|
-- As a special case, we allow casts from CHAR(n) that use functions
|
|
|
|
-- declared to take TEXT. This does not pass the binary-coercibility test
|
|
|
|
-- because CHAR(n)-to-TEXT normally invokes rtrim(). However, the results
|
|
|
|
-- are the same, so long as the function is one that ignores trailing blanks.
|
2002-07-19 01:11:32 +02:00
|
|
|
|
|
|
|
SELECT c.*
|
|
|
|
FROM pg_cast c, pg_proc p
|
|
|
|
WHERE c.castfunc = p.oid AND
|
2004-06-16 03:27:00 +02:00
|
|
|
(p.pronargs < 1 OR p.pronargs > 3
|
2004-03-15 02:13:41 +01:00
|
|
|
OR NOT (binary_coercible(c.castsource, p.proargtypes[0])
|
|
|
|
OR (c.castsource = 'character'::regtype AND
|
|
|
|
p.proargtypes[0] = 'text'::regtype))
|
2003-05-26 02:11:29 +02:00
|
|
|
OR NOT binary_coercible(p.prorettype, c.casttarget));
|
2002-07-19 01:11:32 +02:00
|
|
|
|
2004-06-16 03:27:00 +02:00
|
|
|
SELECT c.*
|
|
|
|
FROM pg_cast c, pg_proc p
|
|
|
|
WHERE c.castfunc = p.oid AND
|
|
|
|
((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR
|
|
|
|
(p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype));
|
|
|
|
|
2002-07-19 01:11:32 +02:00
|
|
|
-- Look for binary compatible casts that do not have the reverse
|
|
|
|
-- direction registered as well, or where the reverse direction is not
|
2003-05-26 02:11:29 +02:00
|
|
|
-- also binary compatible. This is legal, but usually not intended.
|
|
|
|
|
|
|
|
-- As of 7.4, this finds the casts from text and varchar to bpchar, because
|
|
|
|
-- those are binary-compatible while the reverse way goes through rtrim().
|
2002-07-19 01:11:32 +02:00
|
|
|
|
2006-01-26 03:35:51 +01:00
|
|
|
-- As of 8.2, this finds the cast from cidr to inet, because that is a
|
|
|
|
-- trivial binary coercion while the other way goes through inet_to_cidr().
|
|
|
|
|
2007-11-27 13:21:05 +01:00
|
|
|
-- As of 8.3, this finds the casts from xml to text, varchar, and bpchar,
|
|
|
|
-- because those are binary-compatible while the reverse goes through
|
|
|
|
-- texttoxml(), which does an XML syntax check.
|
|
|
|
|
2010-09-03 03:34:55 +02:00
|
|
|
-- As of 9.1, this finds the cast from pg_node_tree to text, which we
|
|
|
|
-- intentionally do not provide a reverse pathway for.
|
|
|
|
|
|
|
|
SELECT castsource::regtype, casttarget::regtype, castfunc, castcontext
|
2002-07-19 01:11:32 +02:00
|
|
|
FROM pg_cast c
|
2008-10-31 09:39:22 +01:00
|
|
|
WHERE c.castmethod = 'b' AND
|
2002-08-22 02:01:51 +02:00
|
|
|
NOT EXISTS (SELECT 1 FROM pg_cast k
|
2008-10-31 09:39:22 +01:00
|
|
|
WHERE k.castmethod = 'b' AND
|
2002-07-19 01:11:32 +02:00
|
|
|
k.castsource = c.casttarget AND
|
|
|
|
k.casttarget = c.castsource);
|
2002-04-11 22:00:18 +02:00
|
|
|
|
2016-01-05 21:00:54 +01:00
|
|
|
|
|
|
|
-- **************** pg_conversion ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_conversion fields.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.conname
|
|
|
|
FROM pg_conversion as p1
|
|
|
|
WHERE p1.conproc = 0 OR
|
|
|
|
pg_encoding_to_char(conforencoding) = '' OR
|
|
|
|
pg_encoding_to_char(contoencoding) = '';
|
|
|
|
|
|
|
|
-- Look for conprocs that don't have the expected signature.
|
|
|
|
|
|
|
|
SELECT p.oid, p.proname, c.oid, c.conname
|
|
|
|
FROM pg_proc p, pg_conversion c
|
|
|
|
WHERE p.oid = c.conproc AND
|
|
|
|
(p.prorettype != 'void'::regtype OR p.proretset OR
|
|
|
|
p.pronargs != 5 OR
|
|
|
|
p.proargtypes[0] != 'int4'::regtype OR
|
|
|
|
p.proargtypes[1] != 'int4'::regtype OR
|
|
|
|
p.proargtypes[2] != 'cstring'::regtype OR
|
|
|
|
p.proargtypes[3] != 'internal'::regtype OR
|
|
|
|
p.proargtypes[4] != 'int4'::regtype);
|
|
|
|
|
|
|
|
-- Check for conprocs that don't perform the specific conversion that
|
|
|
|
-- pg_conversion alleges they do, by trying to invoke each conversion
|
|
|
|
-- on some simple ASCII data. (The conproc should throw an error if
|
|
|
|
-- it doesn't accept the encodings that are passed to it.)
|
|
|
|
-- Unfortunately, we can't test non-default conprocs this way, because
|
|
|
|
-- there is no way to ask convert() to invoke them, and we cannot call
|
|
|
|
-- them directly from SQL. But there are no non-default built-in
|
|
|
|
-- conversions anyway.
|
|
|
|
-- (Similarly, this doesn't cope with any search path issues.)
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.conname
|
|
|
|
FROM pg_conversion as p1
|
|
|
|
WHERE condefault AND
|
|
|
|
convert('ABC'::bytea, pg_encoding_to_char(conforencoding),
|
|
|
|
pg_encoding_to_char(contoencoding)) != 'ABC';
|
|
|
|
|
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- **************** pg_operator ****************
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- Look for illegal values in pg_operator fields.
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
SELECT p1.oid, p1.oprname
|
|
|
|
FROM pg_operator as p1
|
|
|
|
WHERE (p1.oprkind != 'b' AND p1.oprkind != 'l' AND p1.oprkind != 'r') OR
|
|
|
|
p1.oprresult = 0 OR p1.oprcode = 0;
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- Look for missing or unwanted operand types
|
1998-10-29 05:25:23 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
SELECT p1.oid, p1.oprname
|
|
|
|
FROM pg_operator as p1
|
|
|
|
WHERE (p1.oprleft = 0 and p1.oprkind != 'l') OR
|
|
|
|
(p1.oprleft != 0 and p1.oprkind = 'l') OR
|
|
|
|
(p1.oprright = 0 and p1.oprkind != 'r') OR
|
|
|
|
(p1.oprright != 0 and p1.oprkind = 'r');
|
1998-10-29 05:25:23 +01:00
|
|
|
|
|
|
|
-- Look for conflicting operator definitions (same names and input datatypes).
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
|
|
|
FROM pg_operator AS p1, pg_operator AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
|
|
|
p1.oprname = p2.oprname AND
|
|
|
|
p1.oprkind = p2.oprkind AND
|
|
|
|
p1.oprleft = p2.oprleft AND
|
|
|
|
p1.oprright = p2.oprright;
|
|
|
|
|
|
|
|
-- Look for commutative operators that don't commute.
|
|
|
|
-- DEFINITIONAL NOTE: If A.oprcom = B, then x A y has the same result as y B x.
|
|
|
|
-- We expect that B will always say that B.oprcom = A as well; that's not
|
|
|
|
-- inherently essential, but it would be inefficient not to mark it so.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
|
|
|
FROM pg_operator AS p1, pg_operator AS p2
|
|
|
|
WHERE p1.oprcom = p2.oid AND
|
|
|
|
(p1.oprkind != 'b' OR
|
|
|
|
p1.oprleft != p2.oprright OR
|
|
|
|
p1.oprright != p2.oprleft OR
|
|
|
|
p1.oprresult != p2.oprresult OR
|
|
|
|
p1.oid != p2.oprcom);
|
|
|
|
|
|
|
|
-- Look for negatory operators that don't agree.
|
|
|
|
-- DEFINITIONAL NOTE: If A.oprnegate = B, then both A and B must yield
|
|
|
|
-- boolean results, and (x A y) == ! (x B y), or the equivalent for
|
|
|
|
-- single-operand operators.
|
|
|
|
-- We expect that B will always say that B.oprnegate = A as well; that's not
|
|
|
|
-- inherently essential, but it would be inefficient not to mark it so.
|
2002-04-11 22:00:18 +02:00
|
|
|
-- Also, A and B had better not be the same operator.
|
1998-10-29 05:25:23 +01:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
|
|
|
|
FROM pg_operator AS p1, pg_operator AS p2
|
|
|
|
WHERE p1.oprnegate = p2.oid AND
|
|
|
|
(p1.oprkind != p2.oprkind OR
|
|
|
|
p1.oprleft != p2.oprleft OR
|
|
|
|
p1.oprright != p2.oprright OR
|
2002-04-25 04:56:56 +02:00
|
|
|
p1.oprresult != 'bool'::regtype OR
|
|
|
|
p2.oprresult != 'bool'::regtype OR
|
2002-04-11 22:00:18 +02:00
|
|
|
p1.oid != p2.oprnegate OR
|
|
|
|
p1.oid = p2.oid);
|
1998-10-29 05:25:23 +01:00
|
|
|
|
2014-08-16 19:22:52 +02:00
|
|
|
-- Make a list of the names of operators that are claimed to be commutator
|
|
|
|
-- pairs. This list will grow over time, but before accepting a new entry
|
|
|
|
-- make sure you didn't link the wrong operators.
|
|
|
|
|
|
|
|
SELECT DISTINCT o1.oprname AS op1, o2.oprname AS op2
|
|
|
|
FROM pg_operator o1, pg_operator o2
|
|
|
|
WHERE o1.oprcom = o2.oid AND o1.oprname <= o2.oprname
|
|
|
|
ORDER BY 1, 2;
|
|
|
|
|
|
|
|
-- Likewise for negator pairs.
|
|
|
|
|
|
|
|
SELECT DISTINCT o1.oprname AS op1, o2.oprname AS op2
|
|
|
|
FROM pg_operator o1, pg_operator o2
|
|
|
|
WHERE o1.oprnegate = o2.oid AND o1.oprname <= o2.oprname
|
|
|
|
ORDER BY 1, 2;
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- A mergejoinable or hashjoinable operator must be binary, must return
|
|
|
|
-- boolean, and must have a commutator (itself, unless it's a cross-type
|
|
|
|
-- operator).
|
1999-03-01 01:10:44 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
SELECT p1.oid, p1.oprname FROM pg_operator AS p1
|
2006-12-23 01:43:13 +01:00
|
|
|
WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
|
|
|
|
(p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
|
2000-07-28 07:07:49 +02:00
|
|
|
|
2007-02-06 04:52:59 +01:00
|
|
|
-- What's more, the commutator had better be mergejoinable/hashjoinable too.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.oprname
|
|
|
|
FROM pg_operator AS p1, pg_operator AS p2
|
|
|
|
WHERE p1.oprcom = p2.oid AND
|
|
|
|
(p1.oprcanmerge != p2.oprcanmerge OR
|
|
|
|
p1.oprcanhash != p2.oprcanhash);
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- Mergejoinable operators should appear as equality members of btree index
|
|
|
|
-- opfamilies.
|
2003-05-26 02:11:29 +02:00
|
|
|
|
1999-04-08 01:33:33 +02:00
|
|
|
SELECT p1.oid, p1.oprname
|
|
|
|
FROM pg_operator AS p1
|
2006-12-23 01:43:13 +01:00
|
|
|
WHERE p1.oprcanmerge AND NOT EXISTS
|
|
|
|
(SELECT 1 FROM pg_amop
|
|
|
|
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
|
|
|
|
amopopr = p1.oid AND amopstrategy = 3);
|
1999-04-08 01:33:33 +02:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- And the converse.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p.amopfamily
|
|
|
|
FROM pg_operator AS p1, pg_amop p
|
|
|
|
WHERE amopopr = p1.oid
|
|
|
|
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
|
|
|
AND amopstrategy = 3
|
|
|
|
AND NOT p1.oprcanmerge;
|
|
|
|
|
|
|
|
-- Hashable operators should appear as members of hash index opfamilies.
|
2003-06-23 00:04:55 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname
|
|
|
|
FROM pg_operator AS p1
|
|
|
|
WHERE p1.oprcanhash AND NOT EXISTS
|
2006-12-23 01:43:13 +01:00
|
|
|
(SELECT 1 FROM pg_amop
|
|
|
|
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
|
|
|
|
amopopr = p1.oid AND amopstrategy = 1);
|
2003-06-23 00:04:55 +02:00
|
|
|
|
2004-06-13 23:57:28 +02:00
|
|
|
-- And the converse.
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.oid, p1.oprname, p.amopfamily
|
|
|
|
FROM pg_operator AS p1, pg_amop p
|
|
|
|
WHERE amopopr = p1.oid
|
|
|
|
AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
|
2004-06-13 23:57:28 +02:00
|
|
|
AND NOT p1.oprcanhash;
|
2003-06-23 00:04:55 +02:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- Check that each operator defined in pg_operator matches its oprcode entry
|
|
|
|
-- in pg_proc. Easiest to do this separately for each oprkind.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprcode = p2.oid AND
|
|
|
|
p1.oprkind = 'b' AND
|
|
|
|
(p2.pronargs != 2
|
2003-05-26 02:11:29 +02:00
|
|
|
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
|
|
|
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
|
|
|
|
OR NOT binary_coercible(p1.oprright, p2.proargtypes[1]));
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprcode = p2.oid AND
|
|
|
|
p1.oprkind = 'l' AND
|
2003-05-26 02:11:29 +02:00
|
|
|
(p2.pronargs != 1
|
|
|
|
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
|
|
|
OR NOT binary_coercible(p1.oprright, p2.proargtypes[0])
|
|
|
|
OR p1.oprleft != 0);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprcode = p2.oid AND
|
|
|
|
p1.oprkind = 'r' AND
|
2003-05-26 02:11:29 +02:00
|
|
|
(p2.pronargs != 1
|
|
|
|
OR NOT binary_coercible(p2.prorettype, p1.oprresult)
|
|
|
|
OR NOT binary_coercible(p1.oprleft, p2.proargtypes[0])
|
|
|
|
OR p1.oprright != 0);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2003-01-15 20:35:48 +01:00
|
|
|
-- If the operator is mergejoinable or hashjoinable, its underlying function
|
|
|
|
-- should not be volatile.
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprcode = p2.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
(p1.oprcanmerge OR p1.oprcanhash) AND
|
2003-01-15 20:35:48 +01:00
|
|
|
p2.provolatile = 'v';
|
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- If oprrest is set, the operator must return boolean,
|
|
|
|
-- and it must link to a proc with the right signature
|
|
|
|
-- to be a restriction selectivity estimator.
|
2002-08-22 02:01:51 +02:00
|
|
|
-- The proc signature we want is: float8 proc(internal, oid, internal, int4)
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprrest = p2.oid AND
|
2002-04-25 04:56:56 +02:00
|
|
|
(p1.oprresult != 'bool'::regtype OR
|
|
|
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
2001-05-20 22:28:20 +02:00
|
|
|
p2.pronargs != 4 OR
|
2002-08-22 02:01:51 +02:00
|
|
|
p2.proargtypes[0] != 'internal'::regtype OR
|
|
|
|
p2.proargtypes[1] != 'oid'::regtype OR
|
|
|
|
p2.proargtypes[2] != 'internal'::regtype OR
|
|
|
|
p2.proargtypes[3] != 'int4'::regtype);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
-- If oprjoin is set, the operator must be a binary boolean op,
|
|
|
|
-- and it must link to a proc with the right signature
|
|
|
|
-- to be a join selectivity estimator.
|
2008-08-16 02:01:38 +02:00
|
|
|
-- The proc signature we want is: float8 proc(internal, oid, internal, int2, internal)
|
|
|
|
-- (Note: the old signature with only 4 args is still allowed, but no core
|
|
|
|
-- estimator should be using it.)
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
|
|
|
|
FROM pg_operator AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oprjoin = p2.oid AND
|
2002-04-25 04:56:56 +02:00
|
|
|
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
|
|
|
|
p2.prorettype != 'float8'::regtype OR p2.proretset OR
|
2008-08-16 02:01:38 +02:00
|
|
|
p2.pronargs != 5 OR
|
2002-08-22 02:01:51 +02:00
|
|
|
p2.proargtypes[0] != 'internal'::regtype OR
|
|
|
|
p2.proargtypes[1] != 'oid'::regtype OR
|
2003-01-28 23:13:41 +01:00
|
|
|
p2.proargtypes[2] != 'internal'::regtype OR
|
2008-08-16 02:01:38 +02:00
|
|
|
p2.proargtypes[3] != 'int2'::regtype OR
|
|
|
|
p2.proargtypes[4] != 'internal'::regtype);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2011-03-03 07:33:19 +01:00
|
|
|
-- Insist that all built-in pg_operator entries have descriptions
|
|
|
|
SELECT p1.oid, p1.oprname
|
|
|
|
FROM pg_operator as p1 LEFT JOIN pg_description as d
|
|
|
|
ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
|
|
|
|
WHERE d.classoid IS NULL AND p1.oid <= 9999;
|
|
|
|
|
|
|
|
-- Check that operators' underlying functions have suitable comments,
|
2014-01-11 06:16:08 +01:00
|
|
|
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
|
|
|
|
-- put such comments into pg_proc.h; initdb will generate them as needed.)
|
|
|
|
-- In some cases involving legacy names for operators, there are multiple
|
|
|
|
-- operators referencing the same pg_proc entry, so ignore operators whose
|
|
|
|
-- comments say they are deprecated.
|
2011-03-03 21:55:47 +01:00
|
|
|
-- We also have a few functions that are both operator support and meant to
|
|
|
|
-- be called directly; those should have comments matching their operator.
|
2011-03-03 07:33:19 +01:00
|
|
|
WITH funcdescs AS (
|
2011-03-03 21:55:47 +01:00
|
|
|
SELECT p.oid as p_oid, proname, o.oid as o_oid,
|
2011-03-03 07:33:19 +01:00
|
|
|
obj_description(p.oid, 'pg_proc') as prodesc,
|
|
|
|
'implementation of ' || oprname || ' operator' as expecteddesc,
|
|
|
|
obj_description(o.oid, 'pg_operator') as oprdesc
|
|
|
|
FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
|
|
|
|
WHERE o.oid <= 9999
|
|
|
|
)
|
2011-03-03 21:55:47 +01:00
|
|
|
SELECT * FROM funcdescs
|
2011-03-03 07:33:19 +01:00
|
|
|
WHERE prodesc IS DISTINCT FROM expecteddesc
|
2011-03-03 21:55:47 +01:00
|
|
|
AND oprdesc NOT LIKE 'deprecated%'
|
|
|
|
AND prodesc IS DISTINCT FROM oprdesc;
|
2011-03-03 07:33:19 +01:00
|
|
|
|
2014-01-11 06:16:08 +01:00
|
|
|
-- Show all the operator-implementation functions that have their own
|
|
|
|
-- comments. This should happen only in cases where the function and
|
|
|
|
-- operator syntaxes are both documented at the user level.
|
|
|
|
-- This should be a pretty short list; it's mostly legacy cases.
|
|
|
|
WITH funcdescs AS (
|
|
|
|
SELECT p.oid as p_oid, proname, o.oid as o_oid,
|
|
|
|
obj_description(p.oid, 'pg_proc') as prodesc,
|
|
|
|
'implementation of ' || oprname || ' operator' as expecteddesc,
|
|
|
|
obj_description(o.oid, 'pg_operator') as oprdesc
|
|
|
|
FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
|
|
|
|
WHERE o.oid <= 9999
|
|
|
|
)
|
|
|
|
SELECT p_oid, proname, prodesc FROM funcdescs
|
|
|
|
WHERE prodesc IS DISTINCT FROM expecteddesc
|
|
|
|
AND oprdesc NOT LIKE 'deprecated%'
|
|
|
|
ORDER BY 1;
|
|
|
|
|
2011-03-03 07:33:19 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- **************** pg_aggregate ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_aggregate fields.
|
|
|
|
|
2002-04-11 22:00:18 +02:00
|
|
|
SELECT ctid, aggfnoid::oid
|
1999-03-28 04:07:58 +02:00
|
|
|
FROM pg_aggregate as p1
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
WHERE aggfnoid = 0 OR aggtransfn = 0 OR
|
|
|
|
aggkind NOT IN ('n', 'o', 'h') OR
|
|
|
|
aggnumdirectargs < 0 OR
|
|
|
|
(aggkind = 'n' AND aggnumdirectargs > 0) OR
|
2014-04-12 17:58:53 +02:00
|
|
|
aggtranstype = 0 OR aggtransspace < 0 OR aggmtransspace < 0;
|
2002-04-11 22:00:18 +02:00
|
|
|
|
|
|
|
-- Make sure the matching pg_proc entry is sensible, too.
|
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, p.proname
|
|
|
|
FROM pg_aggregate as a, pg_proc as p
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
(NOT p.proisagg OR p.proretset OR p.pronargs < a.aggnumdirectargs);
|
2002-04-11 22:00:18 +02:00
|
|
|
|
|
|
|
-- Make sure there are no proisagg pg_proc entries without matches.
|
|
|
|
|
|
|
|
SELECT oid, proname
|
|
|
|
FROM pg_proc as p
|
|
|
|
WHERE p.proisagg AND
|
|
|
|
NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2000-07-17 05:05:41 +02:00
|
|
|
-- If there is no finalfn then the output type must be the transtype.
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2002-04-11 22:00:18 +02:00
|
|
|
SELECT a.aggfnoid::oid, p.proname
|
|
|
|
FROM pg_aggregate as a, pg_proc as p
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2000-07-17 05:05:41 +02:00
|
|
|
-- Cross-check transfn against its entry in pg_proc.
|
2003-05-26 02:11:29 +02:00
|
|
|
-- NOTE: use physically_coercible here, not binary_coercible, because
|
|
|
|
-- max and min on abstime are implemented using int4larger/int4smaller.
|
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
2002-04-11 22:00:18 +02:00
|
|
|
WHERE a.aggfnoid = p.oid AND
|
2003-05-26 02:11:29 +02:00
|
|
|
a.aggtransfn = ptr.oid AND
|
|
|
|
(ptr.proretset
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
OR NOT (ptr.pronargs =
|
|
|
|
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
|
|
|
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
2003-05-26 02:11:29 +02:00
|
|
|
OR NOT physically_coercible(ptr.prorettype, a.aggtranstype)
|
|
|
|
OR NOT physically_coercible(a.aggtranstype, ptr.proargtypes[0])
|
2006-07-27 21:52:07 +02:00
|
|
|
OR (p.pronargs > 0 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
|
|
|
OR (p.pronargs > 1 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
|
|
|
OR (p.pronargs > 2 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
-- we could carry the check further, but 3 args is enough for now
|
2006-07-27 21:52:07 +02:00
|
|
|
);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
|
|
|
-- Cross-check finalfn (if present) against its entry in pg_proc.
|
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
SELECT a.aggfnoid::oid, p.proname, pfn.oid, pfn.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS pfn
|
2002-04-11 22:00:18 +02:00
|
|
|
WHERE a.aggfnoid = p.oid AND
|
2003-05-26 02:11:29 +02:00
|
|
|
a.aggfinalfn = pfn.oid AND
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
(pfn.proretset OR
|
|
|
|
NOT binary_coercible(pfn.prorettype, p.prorettype) OR
|
|
|
|
NOT binary_coercible(a.aggtranstype, pfn.proargtypes[0]) OR
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
CASE WHEN a.aggfinalextra THEN pfn.pronargs != p.pronargs + 1
|
|
|
|
ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
|
|
|
|
OR (pfn.pronargs > 1 AND
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
OR (pfn.pronargs > 2 AND
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
OR (pfn.pronargs > 3 AND
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
-- we could carry the check further, but 3 args is enough for now
|
|
|
|
);
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2000-07-18 07:02:19 +02:00
|
|
|
-- If transfn is strict then either initval should be non-NULL, or
|
2003-05-26 02:11:29 +02:00
|
|
|
-- input type should match transtype so that the first non-null input
|
2000-07-18 07:02:19 +02:00
|
|
|
-- can be assigned as the state value.
|
|
|
|
|
2003-05-26 02:11:29 +02:00
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
2002-04-11 22:00:18 +02:00
|
|
|
WHERE a.aggfnoid = p.oid AND
|
2003-05-26 02:11:29 +02:00
|
|
|
a.aggtransfn = ptr.oid AND ptr.proisstrict AND
|
|
|
|
a.agginitval IS NULL AND
|
|
|
|
NOT binary_coercible(p.proargtypes[0], a.aggtranstype);
|
2000-07-18 07:02:19 +02:00
|
|
|
|
2014-04-12 17:58:53 +02:00
|
|
|
-- Check for inconsistent specifications of moving-aggregate columns.
|
|
|
|
|
|
|
|
SELECT ctid, aggfnoid::oid
|
|
|
|
FROM pg_aggregate as p1
|
|
|
|
WHERE aggmtranstype != 0 AND
|
|
|
|
(aggmtransfn = 0 OR aggminvtransfn = 0);
|
|
|
|
|
|
|
|
SELECT ctid, aggfnoid::oid
|
|
|
|
FROM pg_aggregate as p1
|
|
|
|
WHERE aggmtranstype = 0 AND
|
|
|
|
(aggmtransfn != 0 OR aggminvtransfn != 0 OR aggmfinalfn != 0 OR
|
|
|
|
aggmtransspace != 0 OR aggminitval IS NOT NULL);
|
|
|
|
|
|
|
|
-- If there is no mfinalfn then the output type must be the mtranstype.
|
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, p.proname
|
|
|
|
FROM pg_aggregate as a, pg_proc as p
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggmtransfn != 0 AND
|
|
|
|
a.aggmfinalfn = 0 AND p.prorettype != a.aggmtranstype;
|
|
|
|
|
|
|
|
-- Cross-check mtransfn (if present) against its entry in pg_proc.
|
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggmtransfn = ptr.oid AND
|
|
|
|
(ptr.proretset
|
|
|
|
OR NOT (ptr.pronargs =
|
|
|
|
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
|
|
|
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
|
|
|
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
|
|
|
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
|
|
|
OR (p.pronargs > 0 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
|
|
|
OR (p.pronargs > 1 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
|
|
|
OR (p.pronargs > 2 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
|
|
|
-- we could carry the check further, but 3 args is enough for now
|
|
|
|
);
|
|
|
|
|
|
|
|
-- Cross-check minvtransfn (if present) against its entry in pg_proc.
|
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggminvtransfn = ptr.oid AND
|
|
|
|
(ptr.proretset
|
|
|
|
OR NOT (ptr.pronargs =
|
|
|
|
CASE WHEN a.aggkind = 'n' THEN p.pronargs + 1
|
|
|
|
ELSE greatest(p.pronargs - a.aggnumdirectargs, 1) + 1 END)
|
|
|
|
OR NOT physically_coercible(ptr.prorettype, a.aggmtranstype)
|
|
|
|
OR NOT physically_coercible(a.aggmtranstype, ptr.proargtypes[0])
|
|
|
|
OR (p.pronargs > 0 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
|
|
|
|
OR (p.pronargs > 1 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
|
|
|
|
OR (p.pronargs > 2 AND
|
|
|
|
NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
|
|
|
|
-- we could carry the check further, but 3 args is enough for now
|
|
|
|
);
|
|
|
|
|
|
|
|
-- Cross-check mfinalfn (if present) against its entry in pg_proc.
|
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, p.proname, pfn.oid, pfn.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS pfn
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggmfinalfn = pfn.oid AND
|
|
|
|
(pfn.proretset OR
|
|
|
|
NOT binary_coercible(pfn.prorettype, p.prorettype) OR
|
|
|
|
NOT binary_coercible(a.aggmtranstype, pfn.proargtypes[0]) OR
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
CASE WHEN a.aggmfinalextra THEN pfn.pronargs != p.pronargs + 1
|
|
|
|
ELSE pfn.pronargs != a.aggnumdirectargs + 1 END
|
|
|
|
OR (pfn.pronargs > 1 AND
|
2014-04-12 17:58:53 +02:00
|
|
|
NOT binary_coercible(p.proargtypes[0], pfn.proargtypes[1]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
OR (pfn.pronargs > 2 AND
|
2014-04-12 17:58:53 +02:00
|
|
|
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
OR (pfn.pronargs > 3 AND
|
2014-04-12 17:58:53 +02:00
|
|
|
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
|
Allow polymorphic aggregates to have non-polymorphic state data types.
Before 9.4, such an aggregate couldn't be declared, because its final
function would have to have polymorphic result type but no polymorphic
argument, which CREATE FUNCTION would quite properly reject. The
ordered-set-aggregate patch found a workaround: allow the final function
to be declared as accepting additional dummy arguments that have types
matching the aggregate's regular input arguments. However, we failed
to notice that this problem applies just as much to regular aggregates,
despite the fact that we had a built-in regular aggregate array_agg()
that was known to be undeclarable in SQL because its final function
had an illegal signature. So what we should have done, and what this
patch does, is to decouple the extra-dummy-arguments behavior from
ordered-set aggregates and make it generally available for all aggregate
declarations. We have to put this into 9.4 rather than waiting till
later because it slightly alters the rules for declaring ordered-set
aggregates.
The patch turned out a bit bigger than I'd hoped because it proved
necessary to record the extra-arguments option in a new pg_aggregate
column. I'd thought we could just look at the final function's pronargs
at runtime, but that didn't work well for variadic final functions.
It's probably just as well though, because it simplifies life for pg_dump
to record the option explicitly.
While at it, fix array_agg() to have a valid final-function signature,
and add an opr_sanity test to notice future deviations from polymorphic
consistency. I also marked the percentile_cont() aggregates as not
needing extra arguments, since they don't.
2014-04-24 01:17:31 +02:00
|
|
|
-- we could carry the check further, but 3 args is enough for now
|
|
|
|
);
|
2014-04-12 17:58:53 +02:00
|
|
|
|
|
|
|
-- If mtransfn is strict then either minitval should be non-NULL, or
|
|
|
|
-- input type should match mtranstype so that the first non-null input
|
|
|
|
-- can be assigned as the state value.
|
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr
|
|
|
|
WHERE a.aggfnoid = p.oid AND
|
|
|
|
a.aggmtransfn = ptr.oid AND ptr.proisstrict AND
|
|
|
|
a.aggminitval IS NULL AND
|
|
|
|
NOT binary_coercible(p.proargtypes[0], a.aggmtranstype);
|
|
|
|
|
2014-04-13 02:33:09 +02:00
|
|
|
-- mtransfn and minvtransfn should have same strictness setting.
|
2014-04-12 17:58:53 +02:00
|
|
|
|
2014-04-13 02:33:09 +02:00
|
|
|
SELECT a.aggfnoid::oid, p.proname, ptr.oid, ptr.proname, iptr.oid, iptr.proname
|
|
|
|
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS ptr, pg_proc AS iptr
|
2014-04-12 17:58:53 +02:00
|
|
|
WHERE a.aggfnoid = p.oid AND
|
2014-04-13 02:33:09 +02:00
|
|
|
a.aggmtransfn = ptr.oid AND
|
|
|
|
a.aggminvtransfn = iptr.oid AND
|
|
|
|
ptr.proisstrict != iptr.proisstrict;
|
2014-04-12 17:58:53 +02:00
|
|
|
|
2005-04-12 06:26:34 +02:00
|
|
|
-- Cross-check aggsortop (if present) against pg_operator.
|
2012-02-08 18:41:48 +01:00
|
|
|
-- We expect to find entries for bool_and, bool_or, every, max, and min.
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
SELECT DISTINCT proname, oprname
|
|
|
|
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
|
|
|
|
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid
|
2012-02-08 18:41:48 +01:00
|
|
|
ORDER BY 1, 2;
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
-- Check datatypes match
|
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, o.oid
|
|
|
|
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
|
|
|
|
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
|
|
|
|
(oprkind != 'b' OR oprresult != 'boolean'::regtype
|
|
|
|
OR oprleft != p.proargtypes[0] OR oprright != p.proargtypes[0]);
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- Check operator is a suitable btree opfamily member
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
SELECT a.aggfnoid::oid, o.oid
|
|
|
|
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
|
|
|
|
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
NOT EXISTS(SELECT 1 FROM pg_amop
|
|
|
|
WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
|
|
|
AND amopopr = o.oid
|
|
|
|
AND amoplefttype = o.oprleft
|
|
|
|
AND amoprighttype = o.oprright);
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
-- Check correspondence of btree strategies and names
|
|
|
|
|
|
|
|
SELECT DISTINCT proname, oprname, amopstrategy
|
|
|
|
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
|
2006-12-23 01:43:13 +01:00
|
|
|
pg_amop as ao
|
2005-04-12 06:26:34 +02:00
|
|
|
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
amopopr = o.oid AND
|
|
|
|
amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
|
|
|
|
ORDER BY 1, 2;
|
|
|
|
|
2010-08-05 20:21:19 +02:00
|
|
|
-- Check that there are not aggregates with the same name and different
|
|
|
|
-- numbers of arguments. While not technically wrong, we have a project policy
|
|
|
|
-- to avoid this because it opens the door for confusion in connection with
|
|
|
|
-- ORDER BY: novices frequently put the ORDER BY in the wrong place.
|
|
|
|
-- See the fate of the single-argument form of string_agg() for history.
|
Allow aggregate functions to be VARIADIC.
There's no inherent reason why an aggregate function can't be variadic
(even VARIADIC ANY) if its transition function can handle the case.
Indeed, this patch to add the feature touches none of the planner or
executor, and little of the parser; the main missing stuff was DDL and
pg_dump support.
It is true that variadic aggregates can create the same sort of ambiguity
about parameters versus ORDER BY keys that was complained of when we
(briefly) had both one- and two-argument forms of string_agg(). However,
the policy formed in response to that discussion only said that we'd not
create any built-in aggregates with varying numbers of arguments, not that
we shouldn't allow users to do it. So the logical extension of that is
we can allow users to make variadic aggregates as long as we're wary about
shipping any such in core.
In passing, this patch allows aggregate function arguments to be named, to
the extent of remembering the names in pg_proc and dumping them in pg_dump.
You can't yet call an aggregate using named-parameter notation. That seems
like a likely future extension, but it'll take some work, and it's not what
this patch is really about. Likewise, there's still some work needed to
make window functions handle VARIADIC fully, but I left that for another
day.
initdb forced because of new aggvariadic field in Aggref parse nodes.
2013-09-03 23:08:38 +02:00
|
|
|
-- (Note: we don't forbid users from creating such aggregates; the policy is
|
|
|
|
-- just to think twice before creating built-in aggregates like this.)
|
2010-08-05 20:21:19 +02:00
|
|
|
-- The only aggregates that should show up here are count(x) and count(*).
|
|
|
|
|
|
|
|
SELECT p1.oid::regprocedure, p2.oid::regprocedure
|
|
|
|
FROM pg_proc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.oid < p2.oid AND p1.proname = p2.proname AND
|
|
|
|
p1.proisagg AND p2.proisagg AND
|
|
|
|
array_dims(p1.proargtypes) != array_dims(p2.proargtypes)
|
|
|
|
ORDER BY 1;
|
|
|
|
|
Allow aggregate functions to be VARIADIC.
There's no inherent reason why an aggregate function can't be variadic
(even VARIADIC ANY) if its transition function can handle the case.
Indeed, this patch to add the feature touches none of the planner or
executor, and little of the parser; the main missing stuff was DDL and
pg_dump support.
It is true that variadic aggregates can create the same sort of ambiguity
about parameters versus ORDER BY keys that was complained of when we
(briefly) had both one- and two-argument forms of string_agg(). However,
the policy formed in response to that discussion only said that we'd not
create any built-in aggregates with varying numbers of arguments, not that
we shouldn't allow users to do it. So the logical extension of that is
we can allow users to make variadic aggregates as long as we're wary about
shipping any such in core.
In passing, this patch allows aggregate function arguments to be named, to
the extent of remembering the names in pg_proc and dumping them in pg_dump.
You can't yet call an aggregate using named-parameter notation. That seems
like a likely future extension, but it'll take some work, and it's not what
this patch is really about. Likewise, there's still some work needed to
make window functions handle VARIADIC fully, but I left that for another
day.
initdb forced because of new aggvariadic field in Aggref parse nodes.
2013-09-03 23:08:38 +02:00
|
|
|
-- For the same reason, built-in aggregates with default arguments are no good.
|
2010-08-05 20:21:19 +02:00
|
|
|
|
|
|
|
SELECT oid, proname
|
|
|
|
FROM pg_proc AS p
|
|
|
|
WHERE proisagg AND proargdefaults IS NOT NULL;
|
|
|
|
|
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 22:11:35 +01:00
|
|
|
-- For the same reason, we avoid creating built-in variadic aggregates, except
|
|
|
|
-- that variadic ordered-set aggregates are OK (since they have special syntax
|
|
|
|
-- that is not subject to the misplaced ORDER BY issue).
|
|
|
|
|
|
|
|
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';
|
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- **************** pg_opfamily ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_opfamily fields
|
|
|
|
|
|
|
|
SELECT p1.oid
|
|
|
|
FROM pg_opfamily as p1
|
|
|
|
WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
|
2005-04-12 06:26:34 +02:00
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
|
2000-06-19 05:55:01 +02:00
|
|
|
-- **************** pg_opclass ****************
|
|
|
|
|
2001-08-21 18:36:06 +02:00
|
|
|
-- Look for illegal values in pg_opclass fields
|
|
|
|
|
|
|
|
SELECT p1.oid
|
2006-12-23 01:43:13 +01:00
|
|
|
FROM pg_opclass AS p1
|
|
|
|
WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
|
|
|
|
OR p1.opcintype = 0;
|
|
|
|
|
|
|
|
-- opcmethod must match owning opfamily's opfmethod
|
|
|
|
|
|
|
|
SELECT p1.oid, p2.oid
|
|
|
|
FROM pg_opclass AS p1, pg_opfamily AS p2
|
|
|
|
WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
|
2001-08-21 18:36:06 +02:00
|
|
|
|
|
|
|
-- There should not be multiple entries in pg_opclass with opcdefault true
|
2006-12-23 01:43:13 +01:00
|
|
|
-- and the same opcmethod/opcintype combination.
|
2000-06-19 05:55:01 +02:00
|
|
|
|
|
|
|
SELECT p1.oid, p2.oid
|
|
|
|
FROM pg_opclass AS p1, pg_opclass AS p2
|
|
|
|
WHERE p1.oid != p2.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
|
2001-08-21 18:36:06 +02:00
|
|
|
p1.opcdefault AND p2.opcdefault;
|
2000-06-19 05:55:01 +02:00
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
-- Ask access methods to validate opclasses
|
2016-01-22 01:47:15 +01:00
|
|
|
-- (this replaces a lot of SQL-level checks that used to be done in this file)
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
|
|
|
|
SELECT oid, opcname FROM pg_opclass WHERE NOT amvalidate(oid);
|
|
|
|
|
|
|
|
|
|
|
|
-- **************** pg_am ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_am fields
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.amname
|
|
|
|
FROM pg_am AS p1
|
|
|
|
WHERE p1.amhandler = 0;
|
|
|
|
|
|
|
|
-- Check for amhandler functions with the wrong signature
|
|
|
|
|
|
|
|
SELECT p1.oid, p1.amname, p2.oid, p2.proname
|
|
|
|
FROM pg_am AS p1, pg_proc AS p2
|
|
|
|
WHERE p2.oid = p1.amhandler AND
|
|
|
|
(p2.prorettype != 'index_am_handler'::regtype OR p2.proretset
|
|
|
|
OR p2.pronargs != 1
|
|
|
|
OR p2.proargtypes[0] != 'internal'::regtype);
|
|
|
|
|
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- **************** pg_amop ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_amop fields
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amopfamily, p1.amopstrategy
|
1999-03-28 04:07:58 +02:00
|
|
|
FROM pg_amop as p1
|
2006-12-23 01:43:13 +01:00
|
|
|
WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
|
|
|
|
OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
|
|
|
|
|
2010-11-24 20:20:39 +01:00
|
|
|
SELECT p1.amopfamily, p1.amopstrategy
|
|
|
|
FROM pg_amop as p1
|
|
|
|
WHERE NOT ((p1.amoppurpose = 's' AND p1.amopsortfamily = 0) OR
|
|
|
|
(p1.amoppurpose = 'o' AND p1.amopsortfamily <> 0));
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- amopmethod must match owning opfamily's opfmethod
|
|
|
|
|
|
|
|
SELECT p1.oid, p2.oid
|
|
|
|
FROM pg_amop AS p1, pg_opfamily AS p2
|
|
|
|
WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2003-11-12 22:15:59 +01:00
|
|
|
-- Make a list of all the distinct operator names being used in particular
|
|
|
|
-- strategy slots. This is a bit hokey, since the list might need to change
|
|
|
|
-- in future releases, but it's an effective way of spotting mistakes such as
|
2006-12-23 01:43:13 +01:00
|
|
|
-- swapping two operators within a family.
|
2003-11-12 22:15:59 +01:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT DISTINCT amopmethod, amopstrategy, oprname
|
|
|
|
FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
|
2003-11-12 22:15:59 +01:00
|
|
|
ORDER BY 1, 2, 3;
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2010-11-24 20:20:39 +01:00
|
|
|
-- Check that all opclass search operators have selectivity estimators.
|
|
|
|
-- This is not absolutely required, but it seems a reasonable thing
|
|
|
|
-- to insist on for all standard datatypes.
|
2002-04-11 22:00:18 +02:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
|
2002-04-11 22:00:18 +02:00
|
|
|
FROM pg_amop AS p1, pg_operator AS p2
|
2010-11-24 20:20:39 +01:00
|
|
|
WHERE p1.amopopr = p2.oid AND p1.amoppurpose = 's' AND
|
2002-04-11 22:00:18 +02:00
|
|
|
(p2.oprrest = 0 OR p2.oprjoin = 0);
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- Check that each opclass in an opfamily has associated operators, that is
|
|
|
|
-- ones whose oprleft matches opcintype (possibly by coercion).
|
2003-11-12 22:15:59 +01:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.opcname, p1.opcfamily
|
|
|
|
FROM pg_opclass AS p1
|
|
|
|
WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
|
|
|
|
WHERE p2.amopfamily = p1.opcfamily
|
|
|
|
AND binary_coercible(p1.opcintype, p2.amoplefttype));
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2011-12-17 22:41:16 +01:00
|
|
|
-- Check that each operator listed in pg_amop has an associated opclass,
|
|
|
|
-- that is one whose opcintype matches oprleft (possibly by coercion).
|
|
|
|
-- Otherwise the operator is useless because it cannot be matched to an index.
|
|
|
|
-- (In principle it could be useful to list such operators in multiple-datatype
|
|
|
|
-- btree opfamilies, but in practice you'd expect there to be an opclass for
|
|
|
|
-- every datatype the family knows about.)
|
|
|
|
|
|
|
|
SELECT p1.amopfamily, p1.amopstrategy, p1.amopopr
|
|
|
|
FROM pg_amop AS p1
|
|
|
|
WHERE NOT EXISTS(SELECT 1 FROM pg_opclass AS p2
|
|
|
|
WHERE p2.opcfamily = p1.amopfamily
|
|
|
|
AND binary_coercible(p2.opcintype, p1.amoplefttype));
|
|
|
|
|
2004-03-22 02:38:18 +01:00
|
|
|
-- Operators that are primary members of opclasses must be immutable (else
|
|
|
|
-- it suggests that the index ordering isn't fixed). Operators that are
|
|
|
|
-- cross-type members need only be stable, since they are just shorthands
|
|
|
|
-- for index probe queries.
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
2004-03-22 02:38:18 +01:00
|
|
|
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
|
|
|
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
p1.amoplefttype = p1.amoprighttype AND
|
2004-03-22 02:38:18 +01:00
|
|
|
p3.provolatile != 'i';
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
|
2004-03-22 02:38:18 +01:00
|
|
|
FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
|
|
|
|
WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
p1.amoplefttype != p1.amoprighttype AND
|
2004-03-22 02:38:18 +01:00
|
|
|
p3.provolatile = 'v';
|
|
|
|
|
2007-02-06 03:59:15 +01:00
|
|
|
|
1999-03-28 04:07:58 +02:00
|
|
|
-- **************** pg_amproc ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_amproc fields
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amprocfamily, p1.amprocnum
|
1999-03-28 04:07:58 +02:00
|
|
|
FROM pg_amproc as p1
|
2006-12-23 01:43:13 +01:00
|
|
|
WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
|
|
|
|
OR p1.amprocnum < 1 OR p1.amproc = 0;
|
1999-03-28 04:07:58 +02:00
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
-- Support routines that are primary members of opfamilies must be immutable
|
2004-03-22 02:38:18 +01:00
|
|
|
-- (else it suggests that the index ordering isn't fixed). But cross-type
|
|
|
|
-- members need only be stable, since they are just shorthands
|
|
|
|
-- for index probe queries.
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
2004-03-22 02:38:18 +01:00
|
|
|
FROM pg_amproc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.amproc = p2.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
p1.amproclefttype = p1.amprocrighttype AND
|
2004-03-22 02:38:18 +01:00
|
|
|
p2.provolatile != 'i';
|
|
|
|
|
2006-12-23 01:43:13 +01:00
|
|
|
SELECT p1.amprocfamily, p1.amproc, p2.prosrc
|
2004-03-22 02:38:18 +01:00
|
|
|
FROM pg_amproc AS p1, pg_proc AS p2
|
|
|
|
WHERE p1.amproc = p2.oid AND
|
2006-12-23 01:43:13 +01:00
|
|
|
p1.amproclefttype != p1.amprocrighttype AND
|
2004-03-22 02:38:18 +01:00
|
|
|
p2.provolatile = 'v';
|
2015-05-19 17:47:42 +02:00
|
|
|
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
|
2015-05-19 17:47:42 +02:00
|
|
|
-- **************** pg_index ****************
|
|
|
|
|
|
|
|
-- Look for illegal values in pg_index fields.
|
|
|
|
|
|
|
|
SELECT p1.indexrelid, p1.indrelid
|
|
|
|
FROM pg_index as p1
|
|
|
|
WHERE p1.indexrelid = 0 OR p1.indrelid = 0 OR
|
|
|
|
p1.indnatts <= 0 OR p1.indnatts > 32;
|
|
|
|
|
|
|
|
-- oidvector and int2vector fields should be of length indnatts.
|
|
|
|
|
|
|
|
SELECT p1.indexrelid, p1.indrelid
|
|
|
|
FROM pg_index as p1
|
|
|
|
WHERE array_lower(indkey, 1) != 0 OR array_upper(indkey, 1) != indnatts-1 OR
|
|
|
|
array_lower(indclass, 1) != 0 OR array_upper(indclass, 1) != indnatts-1 OR
|
|
|
|
array_lower(indcollation, 1) != 0 OR array_upper(indcollation, 1) != indnatts-1 OR
|
|
|
|
array_lower(indoption, 1) != 0 OR array_upper(indoption, 1) != indnatts-1;
|
|
|
|
|
|
|
|
-- Check that opclasses and collations match the underlying columns.
|
|
|
|
-- (As written, this test ignores expression indexes.)
|
|
|
|
|
|
|
|
SELECT indexrelid::regclass, indrelid::regclass, attname, atttypid::regtype, opcname
|
|
|
|
FROM (SELECT indexrelid, indrelid, unnest(indkey) as ikey,
|
|
|
|
unnest(indclass) as iclass, unnest(indcollation) as icoll
|
|
|
|
FROM pg_index) ss,
|
|
|
|
pg_attribute a,
|
|
|
|
pg_opclass opc
|
|
|
|
WHERE a.attrelid = indrelid AND a.attnum = ikey AND opc.oid = iclass AND
|
|
|
|
(NOT binary_coercible(atttypid, opcintype) OR icoll != attcollation);
|
|
|
|
|
|
|
|
-- For system catalogs, be even tighter: nearly all indexes should be
|
|
|
|
-- exact type matches not binary-coercible matches. At this writing
|
|
|
|
-- the only exception is an OID index on a regproc column.
|
|
|
|
|
|
|
|
SELECT indexrelid::regclass, indrelid::regclass, attname, atttypid::regtype, opcname
|
|
|
|
FROM (SELECT indexrelid, indrelid, unnest(indkey) as ikey,
|
|
|
|
unnest(indclass) as iclass, unnest(indcollation) as icoll
|
|
|
|
FROM pg_index
|
|
|
|
WHERE indrelid < 16384) ss,
|
|
|
|
pg_attribute a,
|
|
|
|
pg_opclass opc
|
|
|
|
WHERE a.attrelid = indrelid AND a.attnum = ikey AND opc.oid = iclass AND
|
|
|
|
(opcintype != atttypid OR icoll != attcollation)
|
|
|
|
ORDER BY 1;
|
|
|
|
|
|
|
|
-- Check for system catalogs with collation-sensitive ordering. This is not
|
|
|
|
-- a representational error in pg_index, but simply wrong catalog design.
|
|
|
|
-- It's bad because we expect to be able to clone template0 and assign the
|
|
|
|
-- copy a different database collation. It would especially not work for
|
|
|
|
-- shared catalogs. Note that although text columns will show a collation
|
|
|
|
-- in indcollation, they're still okay to index with text_pattern_ops,
|
|
|
|
-- so allow that case.
|
|
|
|
|
|
|
|
SELECT indexrelid::regclass, indrelid::regclass, iclass, icoll
|
|
|
|
FROM (SELECT indexrelid, indrelid,
|
|
|
|
unnest(indclass) as iclass, unnest(indcollation) as icoll
|
|
|
|
FROM pg_index
|
|
|
|
WHERE indrelid < 16384) ss
|
|
|
|
WHERE icoll != 0 AND iclass !=
|
|
|
|
(SELECT oid FROM pg_opclass
|
|
|
|
WHERE opcname = 'text_pattern_ops' AND opcmethod =
|
|
|
|
(SELECT oid FROM pg_am WHERE amname = 'btree'));
|