Okay, I'm tired of hearing about this, and I've decided I can make the problem go away with a day or so's concentrated work.
Here is the plan: Create several "pseudo types" (typtype 'p' in pg_type). We already have one pseudo-type (RECORD), plus the logic in heap.c to reject any attempt to create a table column that's of a pseudo-type. I think we need the following pseudotypes: cstring -- represents a null-terminated C string anytype -- for count(*), nullvalue, nonnullvalue *ONLY* anyarraytype -- for array_eq, array_dims void -- result type for functions with no useful result tuple -- result type for BEFORE triggers internal -- catchall for non-SQL internal data structures I am not by any means wedded to the above type names; does anyone have suggestions for better names? (In particular, I am wondering if "tuple" and "internal" would be better named "pg_tuple" and "pg_internal". We might also consider making a type specifically named "trigger" and using that to declare trigger functions, rather than "tuple".) I am also thinking of creating a pseudotype for "opaque" itself, so that we can get rid of the kluge of using type OID 0 in places where a valid type is expected. We cannot remove "opaque" completely (yet) because of backwards compatibility with existing user I/O functions and triggers; but we can see to it that no built-in or contrib function is declared with "opaque". About I/O behavior: the pg_type entries for these pseudo-types will have to have typinput and typoutput functions. In general these I/O routines must just throw errors. Otherwise you could break the intended type safety by supplying user-written constants. For instance, the present definition of RECORD is wrong (sorry Joe) because it uses oidin and oidout; so I could write "SELECT foo('42'::record)" and thereby crash a function expecting RECORD. Not that there will be any such function, but the analogous case with, say, INTERNAL would be bad news. An exception is that void_out should succeed and just return an empty string; this allows functions-returning-void to be called by SELECT and behave reasonably. Less obviously, void_in should succeed (and return nothing interesting, probably just a zero datum; it can ignore its input). This allows plpgsql functions to be defined to return VOID. I am also considering allowing cstring_out to succeed (and, of course, just return a copy of what it's given). That would allow explicit invocation of an output function to work, viz "SELECT cash_out('42'::money)" would actually do what the user expects. This is not really necessary though. We can't allow cstring_in to succeed, although that looks like a no-brainer, because the system isn't ready to support CSTRING Datums in general contexts. Trigger functions will now be expected to take no arguments and return either tuple (or trigger if we call it that) or opaque. It would also be sensible to allow VOID in the case of AFTER triggers, but I'm inclined not to do so: I think it's better that a trigger function be declared in a way that makes it clear it's supposed to be a trigger. If CREATE TRIGGER accepts functions returning void then I think you lose some useful error checking. Should we throw a NOTICE stating that opaque is deprecated if a trigger is declared with opaque? Or should we wait a release or two for that? Similarly, the preferred signature for I/O functions now uses cstring and the function's actual datatype, rather than OPAQUE (and again we could consider throwing a NOTICE). One of the original concerns about this was how to handle the circularity problem for user-defined I/O functions. If we don't do anything special, then it will still work as long as people define the input function first: create function foo_in(cstring) returns foo as ' ... '; -- you'll get a NOTICE here about "type foo is not yet defined" create function foo_out(foo) returns cstring as '...'; -- you'll get another NOTICE here about "foo is only a shell" create type foo (input = foo_in, output = foo_out, ...); Are the notices annoying enough to be a problem? Is there a way around them? Currently, most of the PL languages explicitly check for type opaque as a function argument or result type, and reject it. This should be generalized to "reject any pseudo-type except those explicitly supported" (which will probably be nothing except VOID). Comments? regards, tom lane ---------------------------(end of broadcast)--------------------------- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])