diff options
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/copy2.out | 4 | ||||
| -rw-r--r-- | src/test/regress/expected/create_type.out | 29 | ||||
| -rw-r--r-- | src/test/regress/expected/opr_sanity.out | 46 | ||||
| -rw-r--r-- | src/test/regress/expected/plpgsql.out | 44 | ||||
| -rw-r--r-- | src/test/regress/expected/type_sanity.out | 67 | ||||
| -rw-r--r-- | src/test/regress/input/create_function_1.source | 26 | ||||
| -rw-r--r-- | src/test/regress/output/create_function_1.source | 27 | ||||
| -rw-r--r-- | src/test/regress/regress.c | 62 | ||||
| -rw-r--r-- | src/test/regress/sql/copy2.sql | 4 | ||||
| -rw-r--r-- | src/test/regress/sql/create_type.sql | 26 | ||||
| -rw-r--r-- | src/test/regress/sql/drop.sql | 4 | ||||
| -rw-r--r-- | src/test/regress/sql/opr_sanity.sql | 46 | ||||
| -rw-r--r-- | src/test/regress/sql/plpgsql.sql | 44 | ||||
| -rw-r--r-- | src/test/regress/sql/type_sanity.sql | 54 |
14 files changed, 336 insertions, 147 deletions
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out index 300e1744a24..fa421e40bad 100644 --- a/src/test/regress/expected/copy2.out +++ b/src/test/regress/expected/copy2.out @@ -6,13 +6,13 @@ CREATE TABLE x ( e text ); NOTICE: CREATE TABLE will create implicit sequence 'x_a_seq' for SERIAL column 'x.a' -CREATE FUNCTION fn_x_before () RETURNS OPAQUE AS ' +CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS ' BEGIN NEW.e := ''before trigger fired''::text; return NEW; END; ' language 'plpgsql'; -CREATE FUNCTION fn_x_after () RETURNS OPAQUE AS ' +CREATE FUNCTION fn_x_after () RETURNS TRIGGER AS ' BEGIN UPDATE x set e=''after trigger fired'' where c=''stuff''; return NULL; diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out index 68dc8fbd5e5..a177153d298 100644 --- a/src/test/regress/expected/create_type.out +++ b/src/test/regress/expected/create_type.out @@ -14,18 +14,39 @@ CREATE TYPE city_budget ( element = int4 ); -- Test type-related default values (broken in releases before PG 7.2) +-- Make dummy I/O routines using the existing internal support for int4, text +CREATE FUNCTION int42_in(cstring) + RETURNS int42 + AS 'int4in' + LANGUAGE 'internal' WITH (isStrict); +WARNING: ProcedureCreate: type int42 is not yet defined +CREATE FUNCTION int42_out(int42) + RETURNS cstring + AS 'int4out' + LANGUAGE 'internal' WITH (isStrict); +WARNING: Argument type "int42" is only a shell +CREATE FUNCTION text_w_default_in(cstring) + RETURNS text_w_default + AS 'textin' + LANGUAGE 'internal' WITH (isStrict); +WARNING: ProcedureCreate: type text_w_default is not yet defined +CREATE FUNCTION text_w_default_out(text_w_default) + RETURNS cstring + AS 'textout' + LANGUAGE 'internal' WITH (isStrict); +WARNING: Argument type "text_w_default" is only a shell CREATE TYPE int42 ( internallength = 4, - input = int4in, - output = int4out, + input = int42_in, + output = int42_out, alignment = int4, default = 42, passedbyvalue ); CREATE TYPE text_w_default ( internallength = variable, - input = textin, - output = textout, + input = text_w_default_in, + output = text_w_default_out, alignment = int4, default = 'zippo' ); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index cb1193b0407..efdc8c6a500 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -16,16 +16,23 @@ -- that test creates some bogus operators... -- **************** pg_proc **************** -- Look for illegal values in pg_proc fields. --- NOTE: currently there are a few pg_proc entries that have prorettype = 0. --- Someday that ought to be cleaned up. +-- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put +-- a larger number of proargtypes check clauses in here. If we ever have +-- more-than-10-arg functions in the standard catalogs, extend this query. SELECT p1.oid, p1.proname FROM pg_proc as p1 -WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR - p1.pronargs < 0 OR p1.pronargs > 16) - AND p1.proname !~ '^pl[^_]+_call_handler$' - AND p1.proname !~ '^RI_FKey_' - AND p1.proname !~ 'costestimate$' - AND p1.proname != 'update_pg_pwd_and_pg_group'; +WHERE p1.prolang = 0 OR p1.prorettype = 0 OR + p1.pronargs < 0 OR p1.pronargs > 10 OR + (p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR + (p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR + (p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR + (p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR + (p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR + (p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR + (p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR + (p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR + (p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR + (p1.proargtypes[9] = 0 AND p1.pronargs > 9); oid | proname -----+--------- (0 rows) @@ -217,7 +224,7 @@ WHERE c.castfunc = 0 AND NOT c.castimplicit; SELECT * FROM pg_cast c WHERE c.castfunc = 0 AND - NOT EXISTS (SELECT * FROM pg_cast k + NOT EXISTS (SELECT 1 FROM pg_cast k WHERE k.castfunc = 0 AND k.castsource = c.casttarget AND k.casttarget = c.castsource); @@ -341,7 +348,7 @@ WHERE p1.oprlsortop != 0 AND SELECT p1.oid, p1.oprname FROM pg_operator AS p1 WHERE p1.oprlsortop != 0 AND NOT - EXISTS(SELECT * FROM pg_operator AS p2 WHERE + EXISTS(SELECT 1 FROM pg_operator AS p2 WHERE p2.oprname = '<' AND p2.oprleft = p1.oprleft AND p2.oprright = p1.oprright AND @@ -352,7 +359,7 @@ WHERE p1.oprlsortop != 0 AND NOT SELECT p1.oid, p1.oprname FROM pg_operator AS p1 WHERE p1.oprlsortop != 0 AND NOT - EXISTS(SELECT * FROM pg_operator AS p2 WHERE + EXISTS(SELECT 1 FROM pg_operator AS p2 WHERE p2.oprname = '>' AND p2.oprleft = p1.oprleft AND p2.oprright = p1.oprright AND @@ -468,15 +475,17 @@ WHERE p1.oprcode = p2.oid AND -- 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. --- The proc signature we want is: float8 proc(opaque, oid, opaque, int4) +-- The proc signature we want is: float8 proc(internal, oid, internal, int4) SELECT p1.oid, p1.oprname, p2.oid, p2.proname FROM pg_operator AS p1, pg_proc AS p2 WHERE p1.oprrest = p2.oid AND (p1.oprresult != 'bool'::regtype OR p2.prorettype != 'float8'::regtype OR p2.proretset OR p2.pronargs != 4 OR - p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR - p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 'int4'::regtype); + p2.proargtypes[0] != 'internal'::regtype OR + p2.proargtypes[1] != 'oid'::regtype OR + p2.proargtypes[2] != 'internal'::regtype OR + p2.proargtypes[3] != 'int4'::regtype); oid | oprname | oid | proname -----+---------+-----+--------- (0 rows) @@ -484,15 +493,16 @@ WHERE p1.oprrest = p2.oid AND -- 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. --- The proc signature we want is: float8 proc(opaque, oid, opaque) +-- The proc signature we want is: float8 proc(internal, oid, internal) SELECT p1.oid, p1.oprname, p2.oid, p2.proname FROM pg_operator AS p1, pg_proc AS p2 WHERE p1.oprjoin = p2.oid AND (p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR p2.prorettype != 'float8'::regtype OR p2.proretset OR p2.pronargs != 3 OR - p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR - p2.proargtypes[2] != 0); + p2.proargtypes[0] != 'internal'::regtype OR + p2.proargtypes[1] != 'oid'::regtype OR + p2.proargtypes[2] != 'internal'::regtype); oid | oprname | oid | proname -----+---------+-----+--------- (0 rows) @@ -547,7 +557,7 @@ WHERE a.aggfnoid = p.oid AND a.aggtranstype != p2.prorettype OR a.aggtranstype != p2.proargtypes[0] OR NOT ((p2.pronargs = 2 AND p.proargtypes[0] = p2.proargtypes[1]) OR - (p2.pronargs = 1 AND p.proargtypes[0] = 0))); + (p2.pronargs = 1 AND p.proargtypes[0] = '"any"'::regtype))); aggfnoid | proname | oid | proname ----------+---------+-----+------------- 2121 | max | 768 | int4larger diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 91d7c34b663..7682be33eb7 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -74,7 +74,7 @@ create unique index PHone_name on PHone using btree (slotname bpchar_ops); -- * AFTER UPDATE on Room -- * - If room no changes let wall slots follow -- ************************************************************ -create function tg_room_au() returns opaque as ' +create function tg_room_au() returns trigger as ' begin if new.roomno != old.roomno then update WSlot set roomno = new.roomno where roomno = old.roomno; @@ -88,7 +88,7 @@ create trigger tg_room_au after update -- * AFTER DELETE on Room -- * - delete wall slots in this room -- ************************************************************ -create function tg_room_ad() returns opaque as ' +create function tg_room_ad() returns trigger as ' begin delete from WSlot where roomno = old.roomno; return old; @@ -100,7 +100,7 @@ create trigger tg_room_ad after delete -- * BEFORE INSERT or UPDATE on WSlot -- * - Check that room exists -- ************************************************************ -create function tg_wslot_biu() returns opaque as ' +create function tg_wslot_biu() returns trigger as ' begin if count(*) = 0 from Room where roomno = new.roomno then raise exception ''Room % does not exist'', new.roomno; @@ -114,7 +114,7 @@ create trigger tg_wslot_biu before insert or update -- * AFTER UPDATE on PField -- * - Let PSlots of this field follow -- ************************************************************ -create function tg_pfield_au() returns opaque as ' +create function tg_pfield_au() returns trigger as ' begin if new.name != old.name then update PSlot set pfname = new.name where pfname = old.name; @@ -128,7 +128,7 @@ create trigger tg_pfield_au after update -- * AFTER DELETE on PField -- * - Remove all slots of this patchfield -- ************************************************************ -create function tg_pfield_ad() returns opaque as ' +create function tg_pfield_ad() returns trigger as ' begin delete from PSlot where pfname = old.name; return old; @@ -140,7 +140,7 @@ create trigger tg_pfield_ad after delete -- * BEFORE INSERT or UPDATE on PSlot -- * - Ensure that our patchfield does exist -- ************************************************************ -create function tg_pslot_biu() returns opaque as ' +create function tg_pslot_biu() returns trigger as ' declare pfrec record; rename new to ps; @@ -158,7 +158,7 @@ create trigger tg_pslot_biu before insert or update -- * AFTER UPDATE on System -- * - If system name changes let interfaces follow -- ************************************************************ -create function tg_system_au() returns opaque as ' +create function tg_system_au() returns trigger as ' begin if new.name != old.name then update IFace set sysname = new.name where sysname = old.name; @@ -172,7 +172,7 @@ create trigger tg_system_au after update -- * BEFORE INSERT or UPDATE on IFace -- * - set the slotname to IF.sysname.ifname -- ************************************************************ -create function tg_iface_biu() returns opaque as ' +create function tg_iface_biu() returns trigger as ' declare sname text; sysrec record; @@ -197,7 +197,7 @@ create trigger tg_iface_biu before insert or update -- * AFTER INSERT or UPDATE or DELETE on Hub -- * - insert/delete/rename slots as required -- ************************************************************ -create function tg_hub_a() returns opaque as ' +create function tg_hub_a() returns trigger as ' declare hname text; dummy integer; @@ -250,7 +250,7 @@ end; -- * - prevent from manual manipulation -- * - set the slotname to HS.hubname.slotno -- ************************************************************ -create function tg_hslot_biu() returns opaque as ' +create function tg_hslot_biu() returns trigger as ' declare sname text; xname HSlot.slotname%TYPE; @@ -286,7 +286,7 @@ create trigger tg_hslot_biu before insert or update -- * BEFORE DELETE on HSlot -- * - prevent from manual manipulation -- ************************************************************ -create function tg_hslot_bd() returns opaque as ' +create function tg_hslot_bd() returns trigger as ' declare hubrec record; begin @@ -306,7 +306,7 @@ create trigger tg_hslot_bd before delete -- * BEFORE INSERT on all slots -- * - Check name prefix -- ************************************************************ -create function tg_chkslotname() returns opaque as ' +create function tg_chkslotname() returns trigger as ' begin if substr(new.slotname, 1, 2) != tg_argv[0] then raise exception ''slotname must begin with %'', tg_argv[0]; @@ -328,7 +328,7 @@ create trigger tg_chkslotname before insert -- * BEFORE INSERT or UPDATE on all slots with slotlink -- * - Set slotlink to empty string if NULL value given -- ************************************************************ -create function tg_chkslotlink() returns opaque as ' +create function tg_chkslotlink() returns trigger as ' begin if new.slotlink isnull then new.slotlink := ''''; @@ -350,7 +350,7 @@ create trigger tg_chkslotlink before insert or update -- * BEFORE INSERT or UPDATE on all slots with backlink -- * - Set backlink to empty string if NULL value given -- ************************************************************ -create function tg_chkbacklink() returns opaque as ' +create function tg_chkbacklink() returns trigger as ' begin if new.backlink isnull then new.backlink := ''''; @@ -368,7 +368,7 @@ create trigger tg_chkbacklink before insert or update -- * BEFORE UPDATE on PSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_pslot_bu() returns opaque as ' +create function tg_pslot_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PSlot where slotname = old.slotname; @@ -394,7 +394,7 @@ create trigger tg_pslot_bu before update -- * BEFORE UPDATE on WSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_wslot_bu() returns opaque as ' +create function tg_wslot_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from WSlot where slotname = old.slotname; @@ -420,7 +420,7 @@ create trigger tg_wslot_bu before update -- * BEFORE UPDATE on PLine -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_pline_bu() returns opaque as ' +create function tg_pline_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PLine where slotname = old.slotname; @@ -446,7 +446,7 @@ create trigger tg_pline_bu before update -- * BEFORE UPDATE on IFace -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_iface_bu() returns opaque as ' +create function tg_iface_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from IFace where slotname = old.slotname; @@ -472,7 +472,7 @@ create trigger tg_iface_bu before update -- * BEFORE UPDATE on HSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_hslot_bu() returns opaque as ' +create function tg_hslot_bu() returns trigger as ' begin if new.slotname != old.slotname or new.hubname != old.hubname then delete from HSlot where slotname = old.slotname; @@ -498,7 +498,7 @@ create trigger tg_hslot_bu before update -- * BEFORE UPDATE on PHone -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_phone_bu() returns opaque as ' +create function tg_phone_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PHone where slotname = old.slotname; @@ -522,7 +522,7 @@ create trigger tg_phone_bu before update -- * AFTER INSERT or UPDATE or DELETE on slot with backlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ -create function tg_backlink_a() returns opaque as ' +create function tg_backlink_a() returns trigger as ' declare dummy integer; begin @@ -666,7 +666,7 @@ end; -- * AFTER INSERT or UPDATE or DELETE on slot with slotlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ -create function tg_slotlink_a() returns opaque as ' +create function tg_slotlink_a() returns trigger as ' declare dummy integer; begin diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index 68abfec74f3..e0890fb01af 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -15,13 +15,12 @@ -- Look for illegal values in pg_type fields. SELECT p1.oid, p1.typname FROM pg_type as p1 -WHERE (p1.typlen <= 0 AND p1.typlen != -1) OR - p1.typtype not in('b', 'c', 'd', 'p') OR +WHERE p1.typnamespace = 0 OR + (p1.typlen <= 0 AND p1.typlen != -1) OR + (p1.typtype not in ('b', 'c', 'd', 'p')) OR NOT p1.typisdefined OR - (p1.typalign != 'c' AND p1.typalign != 's' AND - p1.typalign != 'i' AND p1.typalign != 'd') OR - (p1.typstorage != 'p' AND p1.typstorage != 'x' AND - p1.typstorage != 'e' AND p1.typstorage != 'm'); + (p1.typalign not in ('c', 's', 'i', 'd')) OR + (p1.typstorage not in ('p', 'x', 'e', 'm')); oid | typname -----+--------- (0 rows) @@ -91,27 +90,59 @@ WHERE p1.typtype != 'c' AND (0 rows) -- Check for bogus typinput routines --- FIXME: ought to check prorettype, but there are special cases that make it --- hard: prorettype might be binary-compatible with the type but not the same, --- and for array types array_in's result has nothing to do with anything. SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2 -WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND - (p2.pronargs != 1 OR p2.proretset) AND - (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype); +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR + (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND + p2.proargtypes[1] = 'oid'::regtype AND + p2.proargtypes[2] = 'int4'::regtype)); + oid | typname | oid | proname +-----+---------+-----+--------- +(0 rows) + +-- As of 7.3, this check finds SET and refcursor, which are borrowing +-- other types' I/O routines +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + (p1.typelem != 0 AND p1.typlen < 0) AND NOT + (p2.prorettype = p1.oid AND NOT p2.proretset); + oid | typname | oid | proname +------+-----------+-----+----------- + 32 | SET | 109 | unknownin + 1790 | refcursor | 46 | textin +(2 rows) + +-- Varlena array types will point to array_in +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND + (p1.typelem != 0 AND p1.typlen < 0) AND NOT + (p2.oid = 'array_in'::regproc); oid | typname | oid | proname -----+---------+-----+--------- (0 rows) -- Check for bogus typoutput routines --- The first OR subclause detects bogus non-array cases, --- the second one detects bogus array cases. --- FIXME: ought to check prorettype, but not clear what it should be. +-- As of 7.3, this check finds SET and refcursor, which are borrowing +-- other types' I/O routines +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + ((p2.pronargs = 1 AND p2.proargtypes[0] = p1.oid) OR + (p2.oid = 'array_out'::regproc AND + p1.typelem != 0)); + oid | typname | oid | proname +------+-----------+-----+------------ + 32 | SET | 110 | unknownout + 1790 | refcursor | 47 | textout +(2 rows) + SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2 -WHERE p1.typoutput = p2.oid AND p1.typtype = 'b' AND - (p2.pronargs != 1 OR p2.proretset) AND - (p2.pronargs != 2 OR p2.proretset OR p1.typelem = 0); +WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + (p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); oid | typname | oid | proname -----+---------+-----+--------- (0 rows) diff --git a/src/test/regress/input/create_function_1.source b/src/test/regress/input/create_function_1.source index 14ae6ff2bbb..f657e3740cd 100644 --- a/src/test/regress/input/create_function_1.source +++ b/src/test/regress/input/create_function_1.source @@ -2,38 +2,48 @@ -- CREATE_FUNCTION_1 -- -CREATE FUNCTION widget_in(opaque) +CREATE FUNCTION widget_in(cstring) RETURNS widget AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; -CREATE FUNCTION widget_out(opaque) - RETURNS opaque +CREATE FUNCTION widget_out(widget) + RETURNS cstring + AS '@abs_builddir@/regress@DLSUFFIX@' + LANGUAGE 'c'; + +CREATE FUNCTION int44in(cstring) + RETURNS city_budget + AS '@abs_builddir@/regress@DLSUFFIX@' + LANGUAGE 'c'; + +CREATE FUNCTION int44out(city_budget) + RETURNS cstring AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; CREATE FUNCTION check_primary_key () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION check_foreign_key () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION autoinc () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION funny_dup17 () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION ttdummy () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'C'; diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source index 2c98b6c2eac..9632114f93c 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -1,33 +1,44 @@ -- -- CREATE_FUNCTION_1 -- -CREATE FUNCTION widget_in(opaque) +CREATE FUNCTION widget_in(cstring) RETURNS widget AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; WARNING: ProcedureCreate: type widget is not yet defined -CREATE FUNCTION widget_out(opaque) - RETURNS opaque +CREATE FUNCTION widget_out(widget) + RETURNS cstring AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; +WARNING: Argument type "widget" is only a shell +CREATE FUNCTION int44in(cstring) + RETURNS city_budget + AS '@abs_builddir@/regress@DLSUFFIX@' + LANGUAGE 'c'; +WARNING: ProcedureCreate: type city_budget is not yet defined +CREATE FUNCTION int44out(city_budget) + RETURNS cstring + AS '@abs_builddir@/regress@DLSUFFIX@' + LANGUAGE 'c'; +WARNING: Argument type "city_budget" is only a shell CREATE FUNCTION check_primary_key () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION check_foreign_key () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION autoinc () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION funny_dup17 () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION ttdummy () - RETURNS opaque + RETURNS trigger AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'C'; CREATE FUNCTION set_ttdummy (int4) diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index 3ef2c1b6db7..2965dca69de 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -1,5 +1,5 @@ /* - * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.50 2002/03/06 06:10:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.51 2002/08/22 00:01:51 tgl Exp $ */ #include "postgres.h" @@ -26,6 +26,8 @@ extern Datum overpaid(PG_FUNCTION_ARGS); extern Datum boxarea(PG_FUNCTION_ARGS); extern char *reverse_name(char *string); extern int oldstyle_length(int n, text *t); +extern Datum int44in(PG_FUNCTION_ARGS); +extern Datum int44out(PG_FUNCTION_ARGS); /* ** Distance from a point to a path @@ -684,3 +686,61 @@ set_ttdummy(PG_FUNCTION_ARGS) PG_RETURN_INT32(1); } + + +/* + * Type int44 has no real-world use, but the regression tests use it. + * It's a four-element vector of int4's. + */ + +/* + * int44in - converts "num num ..." to internal form + * + * Note: Fills any missing positions with zeroes. + */ +PG_FUNCTION_INFO_V1(int44in); + +Datum +int44in(PG_FUNCTION_ARGS) +{ + char *input_string = PG_GETARG_CSTRING(0); + int32 *result = (int32 *) palloc(4 * sizeof(int32)); + int i; + + i = sscanf(input_string, + "%d, %d, %d, %d", + &result[0], + &result[1], + &result[2], + &result[3]); + while (i < 4) + result[i++] = 0; + + PG_RETURN_POINTER(result); +} + +/* + * int44out - converts internal form to "num num ..." + */ +PG_FUNCTION_INFO_V1(int44out); + +Datum +int44out(PG_FUNCTION_ARGS) +{ + int32 *an_array = (int32 *) PG_GETARG_POINTER(0); + char *result = (char *) palloc(16 * 4); /* Allow 14 digits + + * sign */ + int i; + char *walk; + + walk = result; + for (i = 0; i < 4; i++) + { + pg_ltoa(an_array[i], walk); + while (*++walk != '\0') + ; + *walk++ = ' '; + } + *--walk = '\0'; + PG_RETURN_CSTRING(result); +} diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql index 4f0d50247f1..72c52dba113 100644 --- a/src/test/regress/sql/copy2.sql +++ b/src/test/regress/sql/copy2.sql @@ -6,14 +6,14 @@ CREATE TABLE x ( e text ); -CREATE FUNCTION fn_x_before () RETURNS OPAQUE AS ' +CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS ' BEGIN NEW.e := ''before trigger fired''::text; return NEW; END; ' language 'plpgsql'; -CREATE FUNCTION fn_x_after () RETURNS OPAQUE AS ' +CREATE FUNCTION fn_x_after () RETURNS TRIGGER AS ' BEGIN UPDATE x set e=''after trigger fired'' where c=''stuff''; return NULL; diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql index 9b37981bd49..ddcba72624e 100644 --- a/src/test/regress/sql/create_type.sql +++ b/src/test/regress/sql/create_type.sql @@ -18,10 +18,28 @@ CREATE TYPE city_budget ( -- Test type-related default values (broken in releases before PG 7.2) +-- Make dummy I/O routines using the existing internal support for int4, text +CREATE FUNCTION int42_in(cstring) + RETURNS int42 + AS 'int4in' + LANGUAGE 'internal' WITH (isStrict); +CREATE FUNCTION int42_out(int42) + RETURNS cstring + AS 'int4out' + LANGUAGE 'internal' WITH (isStrict); +CREATE FUNCTION text_w_default_in(cstring) + RETURNS text_w_default + AS 'textin' + LANGUAGE 'internal' WITH (isStrict); +CREATE FUNCTION text_w_default_out(text_w_default) + RETURNS cstring + AS 'textout' + LANGUAGE 'internal' WITH (isStrict); + CREATE TYPE int42 ( internallength = 4, - input = int4in, - output = int4out, + input = int42_in, + output = int42_out, alignment = int4, default = 42, passedbyvalue @@ -29,8 +47,8 @@ CREATE TYPE int42 ( CREATE TYPE text_w_default ( internallength = variable, - input = textin, - output = textout, + input = text_w_default_in, + output = text_w_default_out, alignment = int4, default = 'zippo' ); diff --git a/src/test/regress/sql/drop.sql b/src/test/regress/sql/drop.sql index a466e6f7c21..2b143d95bc7 100644 --- a/src/test/regress/sql/drop.sql +++ b/src/test/regress/sql/drop.sql @@ -24,9 +24,9 @@ DROP FUNCTION equipment(hobbies_r); DROP FUNCTION user_relns(); -DROP FUNCTION widget_in(opaque); +DROP FUNCTION widget_in(cstring); -DROP FUNCTION widget_out(opaque); +DROP FUNCTION widget_out(widget); DROP FUNCTION pt_in_widget(point,widget); diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 9d08dbd5bb3..d9be98a5fd3 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -18,17 +18,24 @@ -- **************** pg_proc **************** -- Look for illegal values in pg_proc fields. --- NOTE: currently there are a few pg_proc entries that have prorettype = 0. --- Someday that ought to be cleaned up. +-- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put +-- a larger number of proargtypes check clauses in here. If we ever have +-- more-than-10-arg functions in the standard catalogs, extend this query. SELECT p1.oid, p1.proname FROM pg_proc as p1 -WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR - p1.pronargs < 0 OR p1.pronargs > 16) - AND p1.proname !~ '^pl[^_]+_call_handler$' - AND p1.proname !~ '^RI_FKey_' - AND p1.proname !~ 'costestimate$' - AND p1.proname != 'update_pg_pwd_and_pg_group'; +WHERE p1.prolang = 0 OR p1.prorettype = 0 OR + p1.pronargs < 0 OR p1.pronargs > 10 OR + (p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR + (p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR + (p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR + (p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR + (p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR + (p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR + (p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR + (p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR + (p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR + (p1.proargtypes[9] = 0 AND p1.pronargs > 9); -- Look for conflicting proc definitions (same names and input datatypes). -- (This test should be dead code now that we have the unique index @@ -174,7 +181,7 @@ WHERE c.castfunc = 0 AND NOT c.castimplicit; SELECT * FROM pg_cast c WHERE c.castfunc = 0 AND - NOT EXISTS (SELECT * FROM pg_cast k + NOT EXISTS (SELECT 1 FROM pg_cast k WHERE k.castfunc = 0 AND k.castsource = c.casttarget AND k.casttarget = c.castsource); @@ -279,7 +286,7 @@ WHERE p1.oprlsortop != 0 AND SELECT p1.oid, p1.oprname FROM pg_operator AS p1 WHERE p1.oprlsortop != 0 AND NOT - EXISTS(SELECT * FROM pg_operator AS p2 WHERE + EXISTS(SELECT 1 FROM pg_operator AS p2 WHERE p2.oprname = '<' AND p2.oprleft = p1.oprleft AND p2.oprright = p1.oprright AND @@ -287,7 +294,7 @@ WHERE p1.oprlsortop != 0 AND NOT SELECT p1.oid, p1.oprname FROM pg_operator AS p1 WHERE p1.oprlsortop != 0 AND NOT - EXISTS(SELECT * FROM pg_operator AS p2 WHERE + EXISTS(SELECT 1 FROM pg_operator AS p2 WHERE p2.oprname = '>' AND p2.oprleft = p1.oprleft AND p2.oprright = p1.oprright AND @@ -386,7 +393,7 @@ WHERE p1.oprcode = p2.oid AND -- 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. --- The proc signature we want is: float8 proc(opaque, oid, opaque, int4) +-- The proc signature we want is: float8 proc(internal, oid, internal, int4) SELECT p1.oid, p1.oprname, p2.oid, p2.proname FROM pg_operator AS p1, pg_proc AS p2 @@ -394,13 +401,15 @@ WHERE p1.oprrest = p2.oid AND (p1.oprresult != 'bool'::regtype OR p2.prorettype != 'float8'::regtype OR p2.proretset OR p2.pronargs != 4 OR - p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR - p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 'int4'::regtype); + p2.proargtypes[0] != 'internal'::regtype OR + p2.proargtypes[1] != 'oid'::regtype OR + p2.proargtypes[2] != 'internal'::regtype OR + p2.proargtypes[3] != 'int4'::regtype); -- 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. --- The proc signature we want is: float8 proc(opaque, oid, opaque) +-- The proc signature we want is: float8 proc(internal, oid, internal) SELECT p1.oid, p1.oprname, p2.oid, p2.proname FROM pg_operator AS p1, pg_proc AS p2 @@ -408,8 +417,9 @@ WHERE p1.oprjoin = p2.oid AND (p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR p2.prorettype != 'float8'::regtype OR p2.proretset OR p2.pronargs != 3 OR - p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR - p2.proargtypes[2] != 0); + p2.proargtypes[0] != 'internal'::regtype OR + p2.proargtypes[1] != 'oid'::regtype OR + p2.proargtypes[2] != 'internal'::regtype); -- **************** pg_aggregate **************** @@ -454,7 +464,7 @@ WHERE a.aggfnoid = p.oid AND a.aggtranstype != p2.prorettype OR a.aggtranstype != p2.proargtypes[0] OR NOT ((p2.pronargs = 2 AND p.proargtypes[0] = p2.proargtypes[1]) OR - (p2.pronargs = 1 AND p.proargtypes[0] = 0))); + (p2.pronargs = 1 AND p.proargtypes[0] = '"any"'::regtype))); -- Cross-check finalfn (if present) against its entry in pg_proc. -- FIXME: what about binary-compatible types? diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 618273823b3..2f967c65ce4 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -107,7 +107,7 @@ create unique index PHone_name on PHone using btree (slotname bpchar_ops); -- * AFTER UPDATE on Room -- * - If room no changes let wall slots follow -- ************************************************************ -create function tg_room_au() returns opaque as ' +create function tg_room_au() returns trigger as ' begin if new.roomno != old.roomno then update WSlot set roomno = new.roomno where roomno = old.roomno; @@ -124,7 +124,7 @@ create trigger tg_room_au after update -- * AFTER DELETE on Room -- * - delete wall slots in this room -- ************************************************************ -create function tg_room_ad() returns opaque as ' +create function tg_room_ad() returns trigger as ' begin delete from WSlot where roomno = old.roomno; return old; @@ -139,7 +139,7 @@ create trigger tg_room_ad after delete -- * BEFORE INSERT or UPDATE on WSlot -- * - Check that room exists -- ************************************************************ -create function tg_wslot_biu() returns opaque as ' +create function tg_wslot_biu() returns trigger as ' begin if count(*) = 0 from Room where roomno = new.roomno then raise exception ''Room % does not exist'', new.roomno; @@ -156,7 +156,7 @@ create trigger tg_wslot_biu before insert or update -- * AFTER UPDATE on PField -- * - Let PSlots of this field follow -- ************************************************************ -create function tg_pfield_au() returns opaque as ' +create function tg_pfield_au() returns trigger as ' begin if new.name != old.name then update PSlot set pfname = new.name where pfname = old.name; @@ -173,7 +173,7 @@ create trigger tg_pfield_au after update -- * AFTER DELETE on PField -- * - Remove all slots of this patchfield -- ************************************************************ -create function tg_pfield_ad() returns opaque as ' +create function tg_pfield_ad() returns trigger as ' begin delete from PSlot where pfname = old.name; return old; @@ -188,7 +188,7 @@ create trigger tg_pfield_ad after delete -- * BEFORE INSERT or UPDATE on PSlot -- * - Ensure that our patchfield does exist -- ************************************************************ -create function tg_pslot_biu() returns opaque as ' +create function tg_pslot_biu() returns trigger as ' declare pfrec record; rename new to ps; @@ -209,7 +209,7 @@ create trigger tg_pslot_biu before insert or update -- * AFTER UPDATE on System -- * - If system name changes let interfaces follow -- ************************************************************ -create function tg_system_au() returns opaque as ' +create function tg_system_au() returns trigger as ' begin if new.name != old.name then update IFace set sysname = new.name where sysname = old.name; @@ -226,7 +226,7 @@ create trigger tg_system_au after update -- * BEFORE INSERT or UPDATE on IFace -- * - set the slotname to IF.sysname.ifname -- ************************************************************ -create function tg_iface_biu() returns opaque as ' +create function tg_iface_biu() returns trigger as ' declare sname text; sysrec record; @@ -254,7 +254,7 @@ create trigger tg_iface_biu before insert or update -- * AFTER INSERT or UPDATE or DELETE on Hub -- * - insert/delete/rename slots as required -- ************************************************************ -create function tg_hub_a() returns opaque as ' +create function tg_hub_a() returns trigger as ' declare hname text; dummy integer; @@ -312,7 +312,7 @@ end; -- * - prevent from manual manipulation -- * - set the slotname to HS.hubname.slotno -- ************************************************************ -create function tg_hslot_biu() returns opaque as ' +create function tg_hslot_biu() returns trigger as ' declare sname text; xname HSlot.slotname%TYPE; @@ -351,7 +351,7 @@ create trigger tg_hslot_biu before insert or update -- * BEFORE DELETE on HSlot -- * - prevent from manual manipulation -- ************************************************************ -create function tg_hslot_bd() returns opaque as ' +create function tg_hslot_bd() returns trigger as ' declare hubrec record; begin @@ -374,7 +374,7 @@ create trigger tg_hslot_bd before delete -- * BEFORE INSERT on all slots -- * - Check name prefix -- ************************************************************ -create function tg_chkslotname() returns opaque as ' +create function tg_chkslotname() returns trigger as ' begin if substr(new.slotname, 1, 2) != tg_argv[0] then raise exception ''slotname must begin with %'', tg_argv[0]; @@ -403,7 +403,7 @@ create trigger tg_chkslotname before insert -- * BEFORE INSERT or UPDATE on all slots with slotlink -- * - Set slotlink to empty string if NULL value given -- ************************************************************ -create function tg_chkslotlink() returns opaque as ' +create function tg_chkslotlink() returns trigger as ' begin if new.slotlink isnull then new.slotlink := ''''; @@ -432,7 +432,7 @@ create trigger tg_chkslotlink before insert or update -- * BEFORE INSERT or UPDATE on all slots with backlink -- * - Set backlink to empty string if NULL value given -- ************************************************************ -create function tg_chkbacklink() returns opaque as ' +create function tg_chkbacklink() returns trigger as ' begin if new.backlink isnull then new.backlink := ''''; @@ -455,7 +455,7 @@ create trigger tg_chkbacklink before insert or update -- * BEFORE UPDATE on PSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_pslot_bu() returns opaque as ' +create function tg_pslot_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PSlot where slotname = old.slotname; @@ -484,7 +484,7 @@ create trigger tg_pslot_bu before update -- * BEFORE UPDATE on WSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_wslot_bu() returns opaque as ' +create function tg_wslot_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from WSlot where slotname = old.slotname; @@ -513,7 +513,7 @@ create trigger tg_wslot_bu before update -- * BEFORE UPDATE on PLine -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_pline_bu() returns opaque as ' +create function tg_pline_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PLine where slotname = old.slotname; @@ -542,7 +542,7 @@ create trigger tg_pline_bu before update -- * BEFORE UPDATE on IFace -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_iface_bu() returns opaque as ' +create function tg_iface_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from IFace where slotname = old.slotname; @@ -571,7 +571,7 @@ create trigger tg_iface_bu before update -- * BEFORE UPDATE on HSlot -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_hslot_bu() returns opaque as ' +create function tg_hslot_bu() returns trigger as ' begin if new.slotname != old.slotname or new.hubname != old.hubname then delete from HSlot where slotname = old.slotname; @@ -600,7 +600,7 @@ create trigger tg_hslot_bu before update -- * BEFORE UPDATE on PHone -- * - do delete/insert instead of update if name changes -- ************************************************************ -create function tg_phone_bu() returns opaque as ' +create function tg_phone_bu() returns trigger as ' begin if new.slotname != old.slotname then delete from PHone where slotname = old.slotname; @@ -627,7 +627,7 @@ create trigger tg_phone_bu before update -- * AFTER INSERT or UPDATE or DELETE on slot with backlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ -create function tg_backlink_a() returns opaque as ' +create function tg_backlink_a() returns trigger as ' declare dummy integer; begin @@ -781,7 +781,7 @@ end; -- * AFTER INSERT or UPDATE or DELETE on slot with slotlink -- * - Ensure that the opponent correctly points back to us -- ************************************************************ -create function tg_slotlink_a() returns opaque as ' +create function tg_slotlink_a() returns trigger as ' declare dummy integer; begin diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index 5003ae6b165..0a9701de827 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -18,13 +18,12 @@ SELECT p1.oid, p1.typname FROM pg_type as p1 -WHERE (p1.typlen <= 0 AND p1.typlen != -1) OR - p1.typtype not in('b', 'c', 'd', 'p') OR +WHERE p1.typnamespace = 0 OR + (p1.typlen <= 0 AND p1.typlen != -1) OR + (p1.typtype not in ('b', 'c', 'd', 'p')) OR NOT p1.typisdefined OR - (p1.typalign != 'c' AND p1.typalign != 's' AND - p1.typalign != 'i' AND p1.typalign != 'd') OR - (p1.typstorage != 'p' AND p1.typstorage != 'x' AND - p1.typstorage != 'e' AND p1.typstorage != 'm'); + (p1.typalign not in ('c', 's', 'i', 'd')) OR + (p1.typstorage not in ('p', 'x', 'e', 'm')); -- Look for "pass by value" types that can't be passed by value. @@ -76,26 +75,45 @@ WHERE p1.typtype != 'c' AND (p1.typinput = 0 OR p1.typoutput = 0); -- Check for bogus typinput routines --- FIXME: ought to check prorettype, but there are special cases that make it --- hard: prorettype might be binary-compatible with the type but not the same, --- and for array types array_in's result has nothing to do with anything. SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2 -WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND - (p2.pronargs != 1 OR p2.proretset) AND - (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype); +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR + (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND + p2.proargtypes[1] = 'oid'::regtype AND + p2.proargtypes[2] = 'int4'::regtype)); + +-- As of 7.3, this check finds SET and refcursor, which are borrowing +-- other types' I/O routines +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + (p1.typelem != 0 AND p1.typlen < 0) AND NOT + (p2.prorettype = p1.oid AND NOT p2.proretset); + +-- Varlena array types will point to array_in +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND + (p1.typelem != 0 AND p1.typlen < 0) AND NOT + (p2.oid = 'array_in'::regproc); -- Check for bogus typoutput routines --- The first OR subclause detects bogus non-array cases, --- the second one detects bogus array cases. --- FIXME: ought to check prorettype, but not clear what it should be. + +-- As of 7.3, this check finds SET and refcursor, which are borrowing +-- other types' I/O routines +SELECT p1.oid, p1.typname, p2.oid, p2.proname +FROM pg_type AS p1, pg_proc AS p2 +WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + ((p2.pronargs = 1 AND p2.proargtypes[0] = p1.oid) OR + (p2.oid = 'array_out'::regproc AND + p1.typelem != 0)); SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2 -WHERE p1.typoutput = p2.oid AND p1.typtype = 'b' AND - (p2.pronargs != 1 OR p2.proretset) AND - (p2.pronargs != 2 OR p2.proretset OR p1.typelem = 0); +WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT + (p2.prorettype = 'cstring'::regtype AND NOT p2.proretset); -- **************** pg_class **************** |
