-- Helper functions to deal with cases where binary-coercible matches are
-- allowed.
-- This should match IsBinaryCoercible() in parse_coerce.c.
+-- It doesn't currently know about some cases, notably domains, anyelement,
+-- anynonarray, anyenum, or record, but it doesn't need to (yet).
create function binary_coercible(oid, oid) returns bool as $$
begin
if $1 = $2 then return true; end if;
return false;
end
$$ language plpgsql strict stable;
--- This one ignores castcontext, so it considers only physical equivalence
--- and not whether the coercion can be invoked implicitly.
-create function physically_coercible(oid, oid) returns bool as $$
+-- This one ignores castcontext, so it will allow cases where an explicit
+-- (but still binary) cast would be required to convert the input type.
+-- We don't currently use this for any tests in this file, but it is a
+-- reasonable alternative definition for some scenarios.
+create function explicitly_binary_coercible(oid, oid) returns bool as $$
begin
if $1 = $2 then return true; end if;
if EXISTS(select 1 from pg_catalog.pg_cast where
-- Check that operators' underlying functions have suitable comments,
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
--- put such comments into pg_proc.h; initdb will generate them as needed.)
+-- put such comments into pg_proc.dat; 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.
(0 rows)
-- Cross-check transfn against its entry in pg_proc.
--- NOTE: use physically_coercible here, not binary_coercible, because
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
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.aggtranstype)
- OR NOT physically_coercible(a.aggtranstype, ptr.proargtypes[0])
+ OR NOT binary_coercible(ptr.prorettype, a.aggtranstype)
+ OR NOT binary_coercible(a.aggtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
OR (pfn.pronargs > 3 AND
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
- -- we could carry the check further, but 3 args is enough for now
+ -- we could carry the check further, but 4 args is enough for now
+ OR (pfn.pronargs > 4)
);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
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 NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
+ OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
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 NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
+ OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
OR (pfn.pronargs > 3 AND
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
- -- we could carry the check further, but 3 args is enough for now
+ -- we could carry the check further, but 4 args is enough for now
+ OR (pfn.pronargs > 4)
);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
-- Check that all combine functions have signature
-- combine(transtype, transtype) returns transtype
--- NOTE: use physically_coercible here, not binary_coercible, because
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggcombinefn = p.oid AND
(p.pronargs != 2 OR
p.prorettype != p.proargtypes[0] OR
p.prorettype != p.proargtypes[1] OR
- NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
+ NOT binary_coercible(a.aggtranstype, p.proargtypes[0]));
aggfnoid | proname
----------+---------
(0 rows)
-- allowed.
-- This should match IsBinaryCoercible() in parse_coerce.c.
+-- It doesn't currently know about some cases, notably domains, anyelement,
+-- anynonarray, anyenum, or record, but it doesn't need to (yet).
create function binary_coercible(oid, oid) returns bool as $$
begin
if $1 = $2 then return true; end if;
end
$$ language plpgsql strict stable;
--- This one ignores castcontext, so it considers only physical equivalence
--- and not whether the coercion can be invoked implicitly.
-create function physically_coercible(oid, oid) returns bool as $$
+-- This one ignores castcontext, so it will allow cases where an explicit
+-- (but still binary) cast would be required to convert the input type.
+-- We don't currently use this for any tests in this file, but it is a
+-- reasonable alternative definition for some scenarios.
+create function explicitly_binary_coercible(oid, oid) returns bool as $$
begin
if $1 = $2 then return true; end if;
if EXISTS(select 1 from pg_catalog.pg_cast where
-- Check that operators' underlying functions have suitable comments,
-- namely 'implementation of XXX operator'. (Note: it's not necessary to
--- put such comments into pg_proc.h; initdb will generate them as needed.)
+-- put such comments into pg_proc.dat; 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.
a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;
-- Cross-check transfn against its entry in pg_proc.
--- NOTE: use physically_coercible here, not binary_coercible, because
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
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.aggtranstype)
- OR NOT physically_coercible(a.aggtranstype, ptr.proargtypes[0])
+ OR NOT binary_coercible(ptr.prorettype, a.aggtranstype)
+ OR NOT binary_coercible(a.aggtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
-- Cross-check finalfn (if present) against its entry in pg_proc.
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
OR (pfn.pronargs > 3 AND
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
- -- we could carry the check further, but 3 args is enough for now
+ -- we could carry the check further, but 4 args is enough for now
+ OR (pfn.pronargs > 4)
);
-- If transfn is strict then either initval should be non-NULL, or
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 NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
+ OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
-- Cross-check minvtransfn (if present) against its entry in pg_proc.
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 NOT binary_coercible(ptr.prorettype, a.aggmtranstype)
+ OR NOT binary_coercible(a.aggmtranstype, ptr.proargtypes[0])
OR (p.pronargs > 0 AND
- NOT physically_coercible(p.proargtypes[0], ptr.proargtypes[1]))
+ NOT binary_coercible(p.proargtypes[0], ptr.proargtypes[1]))
OR (p.pronargs > 1 AND
- NOT physically_coercible(p.proargtypes[1], ptr.proargtypes[2]))
+ NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
OR (p.pronargs > 2 AND
- NOT physically_coercible(p.proargtypes[2], ptr.proargtypes[3]))
+ NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-- we could carry the check further, but 3 args is enough for now
+ OR (p.pronargs > 3)
);
-- Cross-check mfinalfn (if present) against its entry in pg_proc.
NOT binary_coercible(p.proargtypes[1], pfn.proargtypes[2]))
OR (pfn.pronargs > 3 AND
NOT binary_coercible(p.proargtypes[2], pfn.proargtypes[3]))
- -- we could carry the check further, but 3 args is enough for now
+ -- we could carry the check further, but 4 args is enough for now
+ OR (pfn.pronargs > 4)
);
-- If mtransfn is strict then either minitval should be non-NULL, or
-- Check that all combine functions have signature
-- combine(transtype, transtype) returns transtype
--- NOTE: use physically_coercible here, not binary_coercible, because
SELECT a.aggfnoid, p.proname
FROM pg_aggregate as a, pg_proc as p
(p.pronargs != 2 OR
p.prorettype != p.proargtypes[0] OR
p.prorettype != p.proargtypes[1] OR
- NOT physically_coercible(a.aggtranstype, p.proargtypes[0]));
+ NOT binary_coercible(a.aggtranstype, p.proargtypes[0]));
-- Check that no combine function for an INTERNAL transtype is strict.