Proposal: make "opaque" obsolete

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: pgsql-hackers(at)postgreSQL(dot)org
Subject: Proposal: make "opaque" obsolete
Date: 2002-08-20 18:08:00
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

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

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

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


regards, tom lane


Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2002-08-20 18:18:59 Re: CREATE CAST WITHOUT FUNCTION should require superuserness?
Previous Message Peter Eisentraut 2002-08-20 18:03:28 Re: [BUGS] Long strings, short varchars