Re: anonymous composite types for Table Functions (aka

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Joe Conway <mail(at)joeconway(dot)com>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: anonymous composite types for Table Functions (aka
Date: 2002-08-04 19:48:29
Message-ID: 200208041948.g74JmT416236@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches


Got it and applied. Thanks. This is a major feature now.

---------------------------------------------------------------------------

Joe Conway wrote:
> Bruce Momjian wrote:
> > I am sorry but I am unable to apply this patch because of the DROP
> > COLUMN patch that was applied since you submitted this.
> >
> > It had rejections in gram.y and parse_relation.c, but those were easy to
> > fix. The big problem is pg_proc.c, where the code changes can not be
> > merged.
> >
> > I am attaching the rejected part of the patch. If you can send me a
> > fixed version of just that change, I can commit the rest.
> >
>
> OK. Here is a patch against current cvs for just pg_proc.c. This
> includes all the changes for that file (i.e. not just the one rejected
> hunk).
>
> Thanks,
>
> Joe
>
>

> Index: src/backend/catalog/pg_proc.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql/src/backend/catalog/pg_proc.c,v
> retrieving revision 1.82
> diff -c -r1.82 pg_proc.c
> *** src/backend/catalog/pg_proc.c 2 Aug 2002 18:15:05 -0000 1.82
> --- src/backend/catalog/pg_proc.c 4 Aug 2002 06:21:51 -0000
> ***************
> *** 25,30 ****
> --- 25,31 ----
> #include "miscadmin.h"
> #include "parser/parse_coerce.h"
> #include "parser/parse_expr.h"
> + #include "parser/parse_relation.h"
> #include "parser/parse_type.h"
> #include "tcop/tcopprot.h"
> #include "utils/builtins.h"
> ***************
> *** 33,39 ****
> #include "utils/syscache.h"
>
>
> ! static void checkretval(Oid rettype, List *queryTreeList);
> Datum fmgr_internal_validator(PG_FUNCTION_ARGS);
> Datum fmgr_c_validator(PG_FUNCTION_ARGS);
> Datum fmgr_sql_validator(PG_FUNCTION_ARGS);
> --- 34,40 ----
> #include "utils/syscache.h"
>
>
> ! static void checkretval(Oid rettype, char fn_typtype, List *queryTreeList);
> Datum fmgr_internal_validator(PG_FUNCTION_ARGS);
> Datum fmgr_c_validator(PG_FUNCTION_ARGS);
> Datum fmgr_sql_validator(PG_FUNCTION_ARGS);
> ***************
> *** 367,460 ****
> */
> tlistlen = ExecCleanTargetListLength(tlist);
>
> - /*
> - * For base-type returns, the target list should have exactly one
> - * entry, and its type should agree with what the user declared. (As
> - * of Postgres 7.2, we accept binary-compatible types too.)
> - */
> typerelid = typeidTypeRelid(rettype);
> - if (typerelid == InvalidOid)
> - {
> - if (tlistlen != 1)
> - elog(ERROR, "function declared to return %s returns multiple columns in final SELECT",
> - format_type_be(rettype));
>
> ! restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
> ! if (!IsBinaryCompatible(restype, rettype))
> ! elog(ERROR, "return type mismatch in function: declared to return %s, returns %s",
> ! format_type_be(rettype), format_type_be(restype));
>
> ! return;
> ! }
>
> - /*
> - * If the target list is of length 1, and the type of the varnode in
> - * the target list matches the declared return type, this is okay.
> - * This can happen, for example, where the body of the function is
> - * 'SELECT func2()', where func2 has the same return type as the
> - * function that's calling it.
> - */
> - if (tlistlen == 1)
> - {
> - restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
> - if (IsBinaryCompatible(restype, rettype))
> return;
> }
>
> ! /*
> ! * By here, the procedure returns a tuple or set of tuples. This part
> ! * of the typechecking is a hack. We look up the relation that is the
> ! * declared return type, and scan the non-deleted attributes to ensure
> ! * that they match the datatypes of the non-resjunk columns.
> ! */
> ! reln = heap_open(typerelid, AccessShareLock);
> ! relnatts = reln->rd_rel->relnatts;
> ! rellogcols = 0; /* we'll count nondeleted cols as we go */
> ! colindex = 0;
> !
> ! foreach(tlistitem, tlist)
> ! {
> ! TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
> ! Form_pg_attribute attr;
> ! Oid tletype;
> ! Oid atttype;
>
> ! if (tle->resdom->resjunk)
> ! continue;
>
> ! do {
> colindex++;
> if (colindex > relnatts)
> ! elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
> ! format_type_be(rettype), rellogcols);
> ! attr = reln->rd_att->attrs[colindex - 1];
> ! } while (attr->attisdropped);
> ! rellogcols++;
> !
> ! tletype = exprType(tle->expr);
> ! atttype = attr->atttypid;
> ! if (!IsBinaryCompatible(tletype, atttype))
> ! elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
> ! format_type_be(rettype),
> ! format_type_be(tletype),
> ! format_type_be(atttype),
> ! rellogcols);
> ! }
> !
> ! for (;;)
> ! {
> ! colindex++;
> ! if (colindex > relnatts)
> ! break;
> ! if (!reln->rd_att->attrs[colindex - 1]->attisdropped)
> ! rellogcols++;
> ! }
>
> ! if (tlistlen != rellogcols)
> ! elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
> ! format_type_be(rettype), rellogcols);
>
> ! heap_close(reln, AccessShareLock);
> }
>
>
> --- 368,480 ----
> */
> tlistlen = ExecCleanTargetListLength(tlist);
>
> typerelid = typeidTypeRelid(rettype);
>
> ! if (fn_typtype == 'b')
> ! {
> ! /*
> ! * For base-type returns, the target list should have exactly one
> ! * entry, and its type should agree with what the user declared. (As
> ! * of Postgres 7.2, we accept binary-compatible types too.)
> ! */
>
> ! if (typerelid == InvalidOid)
> ! {
> ! if (tlistlen != 1)
> ! elog(ERROR, "function declared to return %s returns multiple columns in final SELECT",
> ! format_type_be(rettype));
> !
> ! restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
> ! if (!IsBinaryCompatible(restype, rettype))
> ! elog(ERROR, "return type mismatch in function: declared to return %s, returns %s",
> ! format_type_be(rettype), format_type_be(restype));
>
> return;
> + }
> +
> + /*
> + * If the target list is of length 1, and the type of the varnode in
> + * the target list matches the declared return type, this is okay.
> + * This can happen, for example, where the body of the function is
> + * 'SELECT func2()', where func2 has the same return type as the
> + * function that's calling it.
> + */
> + if (tlistlen == 1)
> + {
> + restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
> + if (IsBinaryCompatible(restype, rettype))
> + return;
> + }
> }
> + else if (fn_typtype == 'c')
> + {
> + /*
> + * By here, the procedure returns a tuple or set of tuples. This part
> + * of the typechecking is a hack. We look up the relation that is the
> + * declared return type, and scan the non-deleted attributes to ensure
> + * that they match the datatypes of the non-resjunk columns.
> + */
> + reln = heap_open(typerelid, AccessShareLock);
> + relnatts = reln->rd_rel->relnatts;
> + rellogcols = 0; /* we'll count nondeleted cols as we go */
> + colindex = 0;
>
> ! foreach(tlistitem, tlist)
> ! {
> ! TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
> ! Form_pg_attribute attr;
> ! Oid tletype;
> ! Oid atttype;
> !
> ! if (tle->resdom->resjunk)
> ! continue;
> !
> ! do {
> ! colindex++;
> ! if (colindex > relnatts)
> ! elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
> ! format_type_be(rettype), rellogcols);
> ! attr = reln->rd_att->attrs[colindex - 1];
> ! } while (attr->attisdropped);
> ! rellogcols++;
>
> ! tletype = exprType(tle->expr);
> ! atttype = attr->atttypid;
> ! if (!IsBinaryCompatible(tletype, atttype))
> ! elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
> ! format_type_be(rettype),
> ! format_type_be(tletype),
> ! format_type_be(atttype),
> ! rellogcols);
> ! }
>
> ! for (;;)
> ! {
> colindex++;
> if (colindex > relnatts)
> ! break;
> ! if (!reln->rd_att->attrs[colindex - 1]->attisdropped)
> ! rellogcols++;
> ! }
>
> ! if (tlistlen != rellogcols)
> ! elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
> ! format_type_be(rettype), rellogcols);
>
> ! heap_close(reln, AccessShareLock);
> !
> ! return;
> ! }
> ! else if (fn_typtype == 'p' && rettype == RECORDOID)
> ! {
> ! /*
> ! * For RECORD return type, defer this check until we get the
> ! * first tuple.
> ! */
> ! return;
> ! }
> ! else
> ! elog(ERROR, "Unknown kind of return type specified for function");
> }
>
>
> ***************
> *** 553,558 ****
> --- 573,579 ----
> bool isnull;
> Datum tmp;
> char *prosrc;
> + char functyptype;
>
> tuple = SearchSysCache(PROCOID, funcoid, 0, 0, 0);
> if (!HeapTupleIsValid(tuple))
> ***************
> *** 569,576 ****
>
> prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
>
> querytree_list = pg_parse_and_rewrite(prosrc, proc->proargtypes, proc->pronargs);
> ! checkretval(proc->prorettype, querytree_list);
>
> ReleaseSysCache(tuple);
> PG_RETURN_BOOL(true);
> --- 590,600 ----
>
> prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp));
>
> + /* check typtype to see if we have a predetermined return type */
> + functyptype = typeid_get_typtype(proc->prorettype);
> +
> querytree_list = pg_parse_and_rewrite(prosrc, proc->proargtypes, proc->pronargs);
> ! checkretval(proc->prorettype, functyptype, querytree_list);
>
> ReleaseSysCache(tuple);
> PG_RETURN_BOOL(true);

>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo(at)postgresql(dot)org

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2002-08-04 19:55:27 Re: anonymous composite types for Table Functions (aka SRFs)
Previous Message Bruce Momjian 2002-08-04 19:48:10 Re: anonymous composite types for Table Functions (aka SRFs)

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2002-08-04 19:55:27 Re: anonymous composite types for Table Functions (aka SRFs)
Previous Message Bruce Momjian 2002-08-04 19:48:10 Re: anonymous composite types for Table Functions (aka SRFs)