Re: anonymous composite types for Table Functions (aka

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: anonymous composite types for Table Functions (aka
Дата
Msg-id 200208041948.g74JmT416236@candle.pha.pa.us
обсуждение исходный текст
Ответ на Re: anonymous composite types for Table Functions (aka  (Joe Conway <mail@joeconway.com>)
Список 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@postgresql.org

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

В списке pgsql-patches по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: anonymous composite types for Table Functions (aka SRFs)
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: anonymous composite types for Table Functions (aka SRFs)