Обсуждение: Getting the oid of an anyelement

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

Getting the oid of an anyelement

От
Scott Bailey
Дата:
If I've got a function (sql or plpgsql) that takes anyelement as a
param, how do I determine the type name or oid that was actually passed
in? I figure there is probably a function for this but darn if I can
find it.

Specifically, I'm trying to make a function like Oracle's dump that will
take anything as input and return the internal representation of it. So
I want to determine what type was passed in and call the appropriate
send function.

  SELECT dump(current_date);

  dump
  ------------------------------------------
  Type=date OID=1082 Len=4 Data=(0,0,13,212)

Re: Getting the oid of an anyelement

От
Pavel Stehule
Дата:
Hello

please, try to look on function pg_typeof

postgres=# CREATE OR REPLACE FUNCTION x(anyelement)
RETURNS oid AS $$
SELECT pg_typeof($1)::oid; $$ LANGUAGE sql;
CREATE FUNCTION
postgres=# select x(10);
 x
----
 23
(1 row)

postgres=# select x(current_date);
  x
------
 1082
(1 row)

postgres=#

regards
Pavel Stehule

2009/9/10 Scott Bailey <artacus@comcast.net>:
> If I've got a function (sql or plpgsql) that takes anyelement as a param,
> how do I determine the type name or oid that was actually passed in? I
> figure there is probably a function for this but darn if I can find it.
>
> Specifically, I'm trying to make a function like Oracle's dump that will
> take anything as input and return the internal representation of it. So I
> want to determine what type was passed in and call the appropriate send
> function.
>
>  SELECT dump(current_date);
>
>  dump
>  ------------------------------------------
>  Type=date OID=1082 Len=4 Data=(0,0,13,212)
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Re: Getting the oid of an anyelement

От
Tom Lane
Дата:
Scott Bailey <artacus@comcast.net> writes:
> Specifically, I'm trying to make a function like Oracle's dump that will
> take anything as input and return the internal representation of it. So
> I want to determine what type was passed in and call the appropriate
> send function.

You would need to write that in C.

            regards, tom lane

Re: Getting the oid of an anyelement

От
Pavel Stehule
Дата:
2009/9/10 Tom Lane <tgl@sss.pgh.pa.us>:
> Scott Bailey <artacus@comcast.net> writes:
>> Specifically, I'm trying to make a function like Oracle's dump that will
>> take anything as input and return the internal representation of it. So
>> I want to determine what type was passed in and call the appropriate
>> send function.
>
> You would need to write that in C.
>

You don't need write it.  orafce has it.

http://archives.postgresql.org/pgsql-committers/2009-02/msg00197.php

regards
Pavel Stehule

>                        regards, tom lane
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Re: Getting the oid of an anyelement

От
Scott Bailey
Дата:
> please, try to look on function pg_typeof

Thanks Pavel. Just what I needed. But you're too late on the orafce
recommendation. I had already written it by the time you posted. I would
have written it any way though because Tom said I couldn't :)

> You would need to write that in C.

Two problems with that Tom. First, and most importantly, I never learned
C. (Otherwise, I'd be helping you guys develop). Second, I've already
determined that I was going to do this and I'm pretty darn hard headed.

So here it is in pl/pgsql.

CREATE OR REPLACE FUNCTION dump(
   p_value     anyelement
) RETURNS text AS
$$
DECLARE
   v_type      TEXT;
   v_oid          INT;
   v_data      BYTEA;
   v_send      TEXT;
BEGIN
   SELECT t.typname, t.oid, t.typsend::text
   INTO v_type, v_oid, v_send
   FROM pg_type t
   WHERE t.oid = pg_typeof($1);

   IF v_send IS NULL OR v_send = '-' THEN
     RAISE EXCEPTION 'Found no send function for %', $1;
   ELSE
     EXECUTE 'SELECT ' || v_send || '(' ||
       quote_literal($1) || '::' || v_type || ')'
     INTO v_data;
   END IF;

   RETURN 'Type=' || v_type ||
     ' OID='      || v_oid ||
     ' Len='      || length(v_data) ||
     ' Data=('    || array_to_string(bytes, ',') || ')'
     FROM (
    SELECT array(
      SELECT get_byte(v_data, i)
      FROM generate_series(0, length(v_data) - 1) i
    ) AS bytes
     ) sub;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE STRICT;


-- Usage --
VALUES (dump(100)),
(dump(10.1)),
(dump(random())),
(dump('foo'::text)),
(dump(current_date)),
(dump(current_timestamp));

  column1
  --------------------------------------------------------------
  Type=int4 OID=23 Len=4 Data=(0,0,0,100)
  Type=numeric OID=1700 Len=12 Data=(0,2,0,0,0,0,0,1,0,10,3,232)
  Type=float8 OID=701 Len=8 Data=(63,236,234,4,253,128,0,0)
  Type=text OID=25 Len=3 Data=(102,111,111)
  Type=date OID=1082 Len=4 Data=(0,0,13,212)
  Type=timestamptz OID=1184 Len=8 Data=(0,1,22,61,166,87,22,96)

Re: Getting the oid of an anyelement

От
Pavel Stehule
Дата:
2009/9/10 Scott Bailey <artacus@comcast.net>:
>> please, try to look on function pg_typeof
>
> Thanks Pavel. Just what I needed. But you're too late on the orafce
> recommendation. I had already written it by the time you posted. I would
> have written it any way though because Tom said I couldn't :)
>
>> You would need to write that in C.
>
> Two problems with that Tom. First, and most importantly, I never learned C.
> (Otherwise, I'd be helping you guys develop). Second, I've already
> determined that I was going to do this and I'm pretty darn hard headed.
>
> So here it is in pl/pgsql.
>
> CREATE OR REPLACE FUNCTION dump(
>  p_value     anyelement
> ) RETURNS text AS
> $$
> DECLARE
>  v_type      TEXT;
>  v_oid       INT;
>  v_data      BYTEA;
>  v_send      TEXT;
> BEGIN
>  SELECT t.typname, t.oid, t.typsend::text
>  INTO v_type, v_oid, v_send
>  FROM pg_type t
>  WHERE t.oid = pg_typeof($1);
>
>  IF v_send IS NULL OR v_send = '-' THEN
>    RAISE EXCEPTION 'Found no send function for %', $1;
>  ELSE
>    EXECUTE 'SELECT ' || v_send || '(' ||
>      quote_literal($1) || '::' || v_type || ')'
>    INTO v_data;
>  END IF;
>
>  RETURN 'Type=' || v_type ||
>    ' OID='      || v_oid ||
>    ' Len='      || length(v_data) ||
>    ' Data=('    || array_to_string(bytes, ',') || ')'
>    FROM (
>        SELECT array(
>          SELECT get_byte(v_data, i)
>          FROM generate_series(0, length(v_data) - 1) i
>        ) AS bytes
>    ) sub;
> END;
> $$ LANGUAGE 'plpgsql' IMMUTABLE STRICT;
>

this code is correct - if you would to search some on disk.

regards
Pavel Stehule

>
> -- Usage --
> VALUES (dump(100)),
> (dump(10.1)),
> (dump(random())),
> (dump('foo'::text)),
> (dump(current_date)),
> (dump(current_timestamp));
>
>  column1
>  --------------------------------------------------------------
>  Type=int4 OID=23 Len=4 Data=(0,0,0,100)
>  Type=numeric OID=1700 Len=12 Data=(0,2,0,0,0,0,0,1,0,10,3,232)
>  Type=float8 OID=701 Len=8 Data=(63,236,234,4,253,128,0,0)
>  Type=text OID=25 Len=3 Data=(102,111,111)
>  Type=date OID=1082 Len=4 Data=(0,0,13,212)
>  Type=timestamptz OID=1184 Len=8 Data=(0,1,22,61,166,87,22,96)
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>