Thanks for the review Pavel. I have taken care of the points you raised.
Please see the updated patch.

Regards,
--Asif

On Wed, Nov 21, 2012 at 1:47 AM, Pavel Stehule <pavel.steh...@gmail.com>wrote:

> related to
> http://archives.postgresql.org/message-id/caauglxwpedfwae6dajmf7sxewfusa0f68p07retbbpf_fsa...@mail.gmail.com
>
> * patched and compiled withou warnings
>
> * All 133 tests passed.
>
>
> but
>
> I don't like
>
> * call invalid function from anonymous block - it is messy (regress
> tests) - there is no reason why do it
>
> +create or replace function foo() returns footype as $$
> +declare
> +  v record;
> +  v2 record;
> +begin
> +  v := (1, 'hello');
> +  v2 := (1, 'hello');
> +  return (v || v2);
> +end;
> +$$ language plpgsql;
> +DO $$
> +declare
> +  v footype;
> +begin
> +  v := foo();
> +  raise info 'x = %', v.x;
> +  raise info 'y = %', v.y;
> +end; $$;
> +ERROR:  operator does not exist: record || record
> +LINE 1: SELECT (v || v2)
> +                  ^
>
> * there is some performance issue
>
> create or replace function fx2(a int)
> returns footype as $$
> declare x footype;
> begin
>   x = (10,20);
>   return x;
> end;
> $$ language plpgsql;
>
> postgres=# select sum(fx2.x) from generate_series(1,100000) g(i),
> lateral fx2(i);
>    sum
> ---------
>  1000000
> (1 row)
>
> Time: 497.129 ms
>
> returns footype as $$
> begin
>   return (10,20);
> end;
> $$ language plpgsql;
>
> postgres=# select sum(fx2.x) from generate_series(1,100000) g(i),
> lateral fx2(i);
>    sum
> ---------
>  1000000
> (1 row)
>
> Time: 941.192 ms
>
> following code has same functionality and it is faster
>
>         if (stmt->expr != NULL)
>         {
>                 if (estate->retistuple)
>                 {
>                         TupleDesc       tupdesc;
>                         Datum           retval;
>                         Oid             rettype;
>                         bool            isnull;
>                         int32           tupTypmod;
>                         Oid             tupType;
>                         HeapTupleHeader         td;
>                         HeapTupleData   tmptup;
>
>                         retval = exec_eval_expr(estate,
>                                                                 stmt->expr,
>                                                                 &isnull,
>                                                                 &rettype);
>
>                         /* Source must be of RECORD or composite type */
>                         if (!type_is_rowtype(rettype))
>                                 ereport(ERROR,
>
> (errcode(ERRCODE_DATATYPE_MISMATCH),
>                                                  errmsg("cannot return
> non-composite value from composite type returning function")));
>
>                         if (!isnull)
>                         {
>                                 /* Source is a tuple Datum, so safe to
> do this: */
>                                 td = DatumGetHeapTupleHeader(retval);
>                                 /* Extract rowtype info and find a tupdesc
> */
>                                 tupType = HeapTupleHeaderGetTypeId(td);
>                                 tupTypmod = HeapTupleHeaderGetTypMod(td);
>                                 tupdesc =
> lookup_rowtype_tupdesc(tupType, tupTypmod);
>
>                                 /* Build a temporary HeapTuple control
> structure */
>                                 tmptup.t_len =
> HeapTupleHeaderGetDatumLength(td);
>                                 ItemPointerSetInvalid(&(tmptup.t_self));
>                                 tmptup.t_tableOid = InvalidOid;
>                                 tmptup.t_data = td;
>
>                                 estate->retval =
> PointerGetDatum(heap_copytuple(&tmptup));
>                                 estate->rettupdesc =
> CreateTupleDescCopy(tupdesc);
>                                 ReleaseTupleDesc(tupdesc);
>                         }
>
>                         estate->retisnull = isnull;
>                 }
>
>
>
> * it is to restrictive (maybe) - almost all plpgsql' statements does
> automatic conversions (IO conversions when is necessary)
>
> create type footype2 as (a numeric, b varchar)
>
> postgres=# create or replace function fx3(a int)
> returns footype2 as
> $$
> begin
>   return (10000000.22234213412342143,'ewqerwqreeeee');
> end;
> $$ language plpgsql;
> CREATE FUNCTION
> postgres=# select fx3(10);
> ERROR:  returned record type does not match expected record type
> DETAIL:  Returned type unknown does not match expected type character
> varying in column 2.
> CONTEXT:  PL/pgSQL function fx3(integer) while casting return value to
> function's return type
> postgres=#
>
> * it doesn't support RETURN NEXT
>
> postgres=# create or replace function fx4()
> postgres-# returns setof footype as $$
> postgres$# begin
> postgres$#   for i in 1..10
> postgres$#   loop
> postgres$#     return next (10,20);
> postgres$#   end loop;
> postgres$#   return;
> postgres$# end;
> postgres$# $$ language plpgsql;
> ERROR:  RETURN NEXT must specify a record or row variable in function
> returning row
> LINE 6:     return next (10,20);
>
> * missing any documentation
>
> * repeated code - following code is used on more places in pl_exec.c
> and maybe it is candidate for subroutine
>
> +                                                       /* Source is a
> tuple Datum, so safe to do this: */
> +                                                       td =
> DatumGetHeapTupleHeader(value);
> +                                                       /* Extract rowtype
> info and find a tupdesc */
> +                                                       tupType =
> HeapTupleHeaderGetTypeId(td);
> +                                                       tupTypmod =
> HeapTupleHeaderGetTypMod(td);
> +                                                       tupdesc =
> lookup_rowtype_tupdesc_copy(tupType, tupTypmod);
> +                                                       /* Build a
> HeapTuple control structure */
> +                                                       htup.t_len =
> HeapTupleHeaderGetDatumLength(td);
> +
> ItemPointerSetInvalid(&(htup.t_self));
> +                                                       htup.t_tableOid =
> InvalidOid;
> +                                                       htup.t_data = td;
> +                                                       tuple =
> heap_copytuple(&htup);
>
> Regards
>
> Pavel Stehule
>

Attachment: return_rowtype.2.patch
Description: Binary data

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to