2008-10-31 10:17:17 +01:00
|
|
|
--
|
|
|
|
-- CREATE_CAST
|
|
|
|
--
|
|
|
|
-- Create some types to test with
|
|
|
|
CREATE TYPE casttesttype;
|
|
|
|
CREATE FUNCTION casttesttype_in(cstring)
|
|
|
|
RETURNS casttesttype
|
|
|
|
AS 'textin'
|
2014-11-05 17:44:06 +01:00
|
|
|
LANGUAGE internal STRICT IMMUTABLE;
|
2008-10-31 10:17:17 +01:00
|
|
|
NOTICE: return type casttesttype is only a shell
|
|
|
|
CREATE FUNCTION casttesttype_out(casttesttype)
|
|
|
|
RETURNS cstring
|
|
|
|
AS 'textout'
|
2014-11-05 17:44:06 +01:00
|
|
|
LANGUAGE internal STRICT IMMUTABLE;
|
2008-10-31 10:17:17 +01:00
|
|
|
NOTICE: argument type casttesttype is only a shell
|
|
|
|
CREATE TYPE casttesttype (
|
|
|
|
internallength = variable,
|
|
|
|
input = casttesttype_in,
|
|
|
|
output = casttesttype_out,
|
|
|
|
alignment = int4
|
|
|
|
);
|
|
|
|
-- a dummy function to test with
|
|
|
|
CREATE FUNCTION casttestfunc(casttesttype) RETURNS int4 LANGUAGE SQL AS
|
|
|
|
$$ SELECT 1; $$;
|
|
|
|
SELECT casttestfunc('foo'::text); -- fails, as there's no cast
|
|
|
|
ERROR: function casttestfunc(text) does not exist
|
|
|
|
LINE 1: SELECT casttestfunc('foo'::text);
|
|
|
|
^
|
|
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
|
|
-- Try binary coercion cast
|
|
|
|
CREATE CAST (text AS casttesttype) WITHOUT FUNCTION;
|
|
|
|
SELECT casttestfunc('foo'::text); -- doesn't work, as the cast is explicit
|
|
|
|
ERROR: function casttestfunc(text) does not exist
|
|
|
|
LINE 1: SELECT casttestfunc('foo'::text);
|
|
|
|
^
|
|
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
|
|
SELECT casttestfunc('foo'::text::casttesttype); -- should work
|
|
|
|
casttestfunc
|
|
|
|
--------------
|
|
|
|
1
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
DROP CAST (text AS casttesttype); -- cleanup
|
|
|
|
-- Try IMPLICIT binary coercion cast
|
|
|
|
CREATE CAST (text AS casttesttype) WITHOUT FUNCTION AS IMPLICIT;
|
|
|
|
SELECT casttestfunc('foo'::text); -- Should work now
|
|
|
|
casttestfunc
|
|
|
|
--------------
|
|
|
|
1
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- Try I/O conversion cast.
|
|
|
|
SELECT 1234::int4::casttesttype; -- No cast yet, should fail
|
|
|
|
ERROR: cannot cast type integer to casttesttype
|
|
|
|
LINE 1: SELECT 1234::int4::casttesttype;
|
2009-11-22 06:20:41 +01:00
|
|
|
^
|
2008-10-31 10:17:17 +01:00
|
|
|
CREATE CAST (int4 AS casttesttype) WITH INOUT;
|
|
|
|
SELECT 1234::int4::casttesttype; -- Should work now
|
|
|
|
casttesttype
|
|
|
|
--------------
|
|
|
|
1234
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
DROP CAST (int4 AS casttesttype);
|
|
|
|
-- Try cast with a function
|
|
|
|
CREATE FUNCTION int4_casttesttype(int4) RETURNS casttesttype LANGUAGE SQL AS
|
|
|
|
$$ SELECT ('foo'::text || $1::text)::casttesttype; $$;
|
|
|
|
CREATE CAST (int4 AS casttesttype) WITH FUNCTION int4_casttesttype(int4) AS IMPLICIT;
|
|
|
|
SELECT 1234::int4::casttesttype; -- Should work now
|
|
|
|
casttesttype
|
|
|
|
--------------
|
|
|
|
foo1234
|
|
|
|
(1 row)
|
|
|
|
|
Record dependencies of a cast on other casts that it requires.
When creating a cast that uses a conversion function, we've
historically allowed the input and result types to be
binary-compatible with the function's input and result types,
rather than necessarily being identical. This means that the new
cast is logically dependent on the binary-compatible cast or casts
that it references: if those are defined by pg_cast entries, and you
try to restore the new cast without having defined them, it'll fail.
Hence, we should make pg_depend entries to record these dependencies
so that pg_dump knows that there is an ordering requirement.
This is not the only place where we allow such shortcuts; aggregate
functions for example are similarly lax, and in principle should gain
similar dependencies. However, for now it seems sufficient to fix
the cast-versus-cast case, as pg_dump's other ordering heuristics
should keep it out of trouble for other object types.
Per report from David Turoň; thanks also to Robert Haas for
preliminary investigation. I considered back-patching, but
seeing that this issue has existed for many years without
previous reports, it's not clear it's worth the trouble.
Moreover, back-patching wouldn't be enough to ensure that the
new pg_depend entries exist in existing databases anyway.
Discussion: https://postgr.es/m/OF0A160F3E.578B15D1-ONC12588DA.003E4857-C12588DA.0045A428@notes.linuxbox.cz
2022-10-17 20:02:05 +02:00
|
|
|
DROP FUNCTION int4_casttesttype(int4) CASCADE;
|
|
|
|
NOTICE: drop cascades to cast from integer to casttesttype
|
|
|
|
-- Try it with a function that requires an implicit cast
|
|
|
|
CREATE FUNCTION bar_int4_text(int4) RETURNS text LANGUAGE SQL AS
|
|
|
|
$$ SELECT ('bar'::text || $1::text); $$;
|
|
|
|
CREATE CAST (int4 AS casttesttype) WITH FUNCTION bar_int4_text(int4) AS IMPLICIT;
|
|
|
|
SELECT 1234::int4::casttesttype; -- Should work now
|
|
|
|
casttesttype
|
|
|
|
--------------
|
|
|
|
bar1234
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
-- check dependencies generated for that
|
|
|
|
SELECT pg_describe_object(classid, objid, objsubid) as obj,
|
|
|
|
pg_describe_object(refclassid, refobjid, refobjsubid) as objref,
|
|
|
|
deptype
|
|
|
|
FROM pg_depend
|
|
|
|
WHERE classid = 'pg_cast'::regclass AND
|
|
|
|
objid = (SELECT oid FROM pg_cast
|
|
|
|
WHERE castsource = 'int4'::regtype
|
|
|
|
AND casttarget = 'casttesttype'::regtype)
|
|
|
|
ORDER BY refclassid;
|
|
|
|
obj | objref | deptype
|
|
|
|
-----------------------------------+---------------------------------+---------
|
|
|
|
cast from integer to casttesttype | type casttesttype | n
|
|
|
|
cast from integer to casttesttype | function bar_int4_text(integer) | n
|
|
|
|
cast from integer to casttesttype | cast from text to casttesttype | n
|
|
|
|
(3 rows)
|
|
|
|
|