Обсуждение: test datatype for ANY

Поиск
Список
Период
Сортировка

test datatype for ANY

От
NosyMan
Дата:
Hi there,

How can I test the type of a parameter passed to a function via ANY data type?
I want something like this:

CREATE OR REPLACE FUNCTION myfunction(_param ANY) RETURNS INTEGER AS $$
    BEGIN
        IF "_param IS OF INTEGER TYPE" THEN
            -- do something with INTEGER
        END IF;
        IF "param is of BOOLEAN TYPE" THEN
            -- do something with BOOLEAN
        END IF;
        RETURN;
    END;
$$ LANGUAGE plpgsql;


Thanks,
Nosy


Re: test datatype for ANY

От
Michael Fuhr
Дата:
On Fri, Feb 11, 2005 at 08:40:53PM +0000, NosyMan wrote:
>
> How can I test the type of a parameter passed to a function via ANY data type?
> I want something like this:
>
> CREATE OR REPLACE FUNCTION myfunction(_param ANY) RETURNS INTEGER AS $$
>     BEGIN
>         IF "_param IS OF INTEGER TYPE" THEN
>             -- do something with INTEGER
>         END IF;

PostgreSQL has an undocumented IS OF construct:

http://archives.postgresql.org/pgsql-general/2005-01/msg00398.php

Example:

  IF param IS OF (integer) THEN
      -- do integer stuff
  ELSIF param IS OF (boolean) THEN
      -- do boolean stuff
  END IF;

Since IS OF is undocumented, I'd be careful about using it.  I don't
know what plans the developers have for it, but I doubt they'll
feel sorry for you if your code breaks because they removed it or
changed its behavior.

See also the coltype() function I posted as part of the same thread
that mentioned IS OF:

http://archives.postgresql.org/pgsql-general/2005-01/msg00390.php

Using coltype(), the above code would look like this:

  IF coltype(param) = 'integer'::regtype THEN
      -- do integer stuff
  ELSIF coltype(param) = 'boolean'::regtype THEN
      -- do boolean stuff
  END IF;

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: test datatype for ANY

От
Tom Lane
Дата:
Michael Fuhr <mike@fuhr.org> writes:
> On Fri, Feb 11, 2005 at 08:40:53PM +0000, NosyMan wrote:
>> I want something like this:
>>
>> CREATE OR REPLACE FUNCTION myfunction(_param ANY) RETURNS INTEGER AS $$

> PostgreSQL has an undocumented IS OF construct:

... which won't help since IS OF is a parse-time test, and he needs a
run-time one.  However, he'll never get that far anyway since plpgsql
doesn't allow ANY parameters.  AFAIK the *only* way you could write such
a function is in C (using get_fn_expr_argtype()).

There are some limited cases you could handle in plpgsql using the
polymorphic-functions stuff (ie, ANYELEMENT not ANY) but it still has
no concept of a run-time type test.

            regards, tom lane

Re: test datatype for ANY

От
Michael Fuhr
Дата:
On Fri, Feb 11, 2005 at 02:32:31PM -0500, Tom Lane wrote:

> There are some limited cases you could handle in plpgsql using the
> polymorphic-functions stuff (ie, ANYELEMENT not ANY) but it still has
> no concept of a run-time type test.

Eh?  What am I misunderstanding then?  The following done in 8.0.1:

CREATE FUNCTION argtype(param anyelement) RETURNS text AS $$
BEGIN
    IF param IS OF (integer) THEN
    RETURN 'integer';
    ELSIF param IS OF (numeric) THEN
    RETURN 'numeric';
    ELSIF param IS OF (boolean) THEN
    RETURN 'boolean';
    ELSIF param IS OF (text) THEN
    RETURN 'text';
    ELSIF param IS OF (date) THEN
    RETURN 'date';
    END IF;

   RETURN 'something else';
END;
$$ LANGUAGE plpgsql IMMUTABLE;

SELECT argtype(1);
 argtype
---------
 integer

SELECT argtype(1.2);
 argtype
---------
 numeric

SELECT argtype('test'::text);
 argtype
---------
 text

SELECT argtype(true);
 argtype
---------
 boolean

CREATE TABLE foo (id integer, foodate date);
INSERT INTO foo VALUES (1, current_date);
SELECT argtype(id) AS idtype, argtype(foodate) AS foodatetype FROM foo;
 idtype  | foodatetype
---------+-------------
 integer | date

SELECT argtype(x) FROM (SELECT foodate FROM foo) AS s(x);
 argtype
---------
 date

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: test datatype for ANY

От
Tom Lane
Дата:
Michael Fuhr <mike@fuhr.org> writes:
> On Fri, Feb 11, 2005 at 02:32:31PM -0500, Tom Lane wrote:
>> There are some limited cases you could handle in plpgsql using the
>> polymorphic-functions stuff (ie, ANYELEMENT not ANY) but it still has
>> no concept of a run-time type test.

> Eh?  What am I misunderstanding then?  The following done in 8.0.1:

> CREATE FUNCTION argtype(param anyelement) RETURNS text AS $$
> BEGIN
>     IF param IS OF (integer) THEN
>     RETURN 'integer';
>     ELSIF param IS OF (numeric) THEN
>     RETURN 'numeric';
>     ELSIF param IS OF (boolean) THEN
>     RETURN 'boolean';
>     ELSIF param IS OF (text) THEN
>     RETURN 'text';
>     ELSIF param IS OF (date) THEN
>     RETURN 'date';
>     END IF;

>    RETURN 'something else';
> END;
> $$ LANGUAGE plpgsql IMMUTABLE;

[ thinks about that for awhile... ]  Oh, I see.  The reason this appears
to work is that plpgsql compiles a separate version of the function for
each actual parameter datatype that is used in a given session.  So in
your example, you get a separate version for integer, numeric, etc.
Within each such version IS OF yields constants, but it "works right"
anyway.

I'm not sure if you can actually tell the difference between this
behavior and a true runtime test; except maybe that the backend would
get a bit bloated if you tried it on hundreds of different types in one
session.

            regards, tom lane

Re: test datatype for ANY

От
Michael Fuhr
Дата:
On Fri, Feb 11, 2005 at 03:37:01PM -0500, Tom Lane wrote:

> [ thinks about that for awhile... ]  Oh, I see.  The reason this appears
> to work is that plpgsql compiles a separate version of the function for
> each actual parameter datatype that is used in a given session.  So in
> your example, you get a separate version for integer, numeric, etc.

Is that the general case for polymorphic functions?

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: test datatype for ANY

От
Tom Lane
Дата:
Michael Fuhr <mike@fuhr.org> writes:
> On Fri, Feb 11, 2005 at 03:37:01PM -0500, Tom Lane wrote:
>> [ thinks about that for awhile... ]  Oh, I see.  The reason this appears
>> to work is that plpgsql compiles a separate version of the function for
>> each actual parameter datatype that is used in a given session.  So in
>> your example, you get a separate version for integer, numeric, etc.

> Is that the general case for polymorphic functions?

AFAIR all the PLs that support polymorphism do it that way.  It's not
the only way it could be done, but it was the easiest way to bolt
polymorphism onto the existing code, which generally assumed that
every data value in the function has a fixed datatype.

            regards, tom lane