1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add a bunch of pseudo-types to replace the behavior formerly associated

with OPAQUE, as per recent pghackers discussion.  I still want to do some
more work on the 'cstring' pseudo-type, but I'm going to commit the bulk
of the changes now before the tree starts shifting under me ...
This commit is contained in:
Tom Lane
2002-08-22 00:01:51 +00:00
parent 606c9b9d4f
commit b663f3443b
126 changed files with 2005 additions and 1205 deletions

View File

@ -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;

View File

@ -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'
);

View File

@ -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

View File

@ -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

View File

@ -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 = '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.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 in ('b', 'p') AND NOT
(p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)

View File

@ -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';

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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'
);

View File

@ -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);

View File

@ -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?

View File

@ -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

View File

@ -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 ****************