Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8efbe30

Browse files
committed
check_sql_fn_retval has always thought that we supported doing
'SELECT foo()' in a SQL function returning a rowtype, to simply passback the results of another function returning the same rowtype.However, that hasn't actually worked in many years. Now it works again.
1 parent3dd1ca0 commit8efbe30

File tree

4 files changed

+68
-41
lines changed

4 files changed

+68
-41
lines changed

‎src/backend/catalog/pg_proc.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.114 2004/04/01 21:28:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.115 2004/04/02 23:14:05 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -362,8 +362,13 @@ create_parameternames_array(int parameterCount, const char *parameterNames[])
362362
* function execution startup.The rettype is then the actual resolved
363363
* output type of the function, rather than the declared type.(Therefore,
364364
* we should never see ANYARRAY or ANYELEMENT as rettype.)
365+
*
366+
* The return value is true if the function returns the entire tuple result
367+
* of its final SELECT, and false otherwise. Note that because we allow
368+
* "SELECT rowtype_expression", this may be false even when the declared
369+
* function return type is a rowtype.
365370
*/
366-
void
371+
bool
367372
check_sql_fn_retval(Oidrettype,charfn_typtype,List*queryTreeList)
368373
{
369374
Query*parse;
@@ -387,7 +392,7 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
387392
errmsg("return type mismatch in function declared to return %s",
388393
format_type_be(rettype)),
389394
errdetail("Function's final statement must be a SELECT.")));
390-
return;
395+
return false;
391396
}
392397

393398
/* find the final query */
@@ -408,7 +413,7 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
408413
errmsg("return type mismatch in function declared to return %s",
409414
format_type_be(rettype)),
410415
errdetail("Function's final statement must not be a SELECT.")));
411-
return;
416+
return false;
412417
}
413418

414419
/* by here, the function is declared to return some type */
@@ -468,7 +473,7 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
468473
{
469474
restype= ((TargetEntry*)lfirst(tlist))->resdom->restype;
470475
if (IsBinaryCoercible(restype,rettype))
471-
return;
476+
return false;/* NOT returning whole tuple */
472477
}
473478

474479
/*
@@ -536,16 +541,31 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
536541
errdetail("Final SELECT returns too few columns.")));
537542

538543
relation_close(reln,AccessShareLock);
544+
545+
/* Report that we are returning entire tuple result */
546+
return true;
539547
}
540548
elseif (rettype==RECORDOID)
541549
{
542-
/* Shouldn't have a typerelid */
543-
Assert(typerelid==InvalidOid);
550+
/*
551+
* If the target list is of length 1, and the type of the varnode
552+
* in the target list matches the declared return type, this is
553+
* okay. This can happen, for example, where the body of the
554+
* function is 'SELECT func2()', where func2 has the same return
555+
* type as the function that's calling it.
556+
*/
557+
if (tlistlen==1)
558+
{
559+
restype= ((TargetEntry*)lfirst(tlist))->resdom->restype;
560+
if (IsBinaryCoercible(restype,rettype))
561+
return false;/* NOT returning whole tuple */
562+
}
544563

545564
/*
546-
*For RECORD return type, defer this check until we get the first
547-
*tuple.
565+
*Otherwise assume we are returning the whole tuple. Crosschecking
566+
*against what the caller expects will happen at runtime.
548567
*/
568+
return true;
549569
}
550570
elseif (rettype==ANYARRAYOID||rettype==ANYELEMENTOID)
551571
{
@@ -560,6 +580,8 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
560580
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
561581
errmsg("return type %s is not supported for SQL functions",
562582
format_type_be(rettype))));
583+
584+
return false;
563585
}
564586

565587

@@ -751,7 +773,8 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
751773
querytree_list=pg_parse_and_rewrite(prosrc,
752774
proc->proargtypes,
753775
proc->pronargs);
754-
check_sql_fn_retval(proc->prorettype,functyptype,querytree_list);
776+
(void)check_sql_fn_retval(proc->prorettype,functyptype,
777+
querytree_list);
755778
}
756779
else
757780
querytree_list=pg_parse_query(prosrc);

‎src/backend/executor/functions.c

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.79 2004/04/01 21:28:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.80 2004/04/02 23:14:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -73,9 +73,7 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
7373

7474

7575
/* non-export function prototypes */
76-
staticexecution_state*init_execution_state(char*src,
77-
Oid*argOidVect,intnargs,
78-
Oidrettype,boolhaspolyarg);
76+
staticexecution_state*init_execution_state(List*queryTree_list);
7977
staticvoidinit_sql_fcache(FmgrInfo*finfo);
8078
staticvoidpostquel_start(execution_state*es,SQLFunctionCachePtrfcache);
8179
staticTupleTableSlot*postquel_getnext(execution_state*es);
@@ -90,25 +88,11 @@ static void ShutdownSQLFunction(Datum arg);
9088

9189

9290
staticexecution_state*
93-
init_execution_state(char*src,Oid*argOidVect,intnargs,
94-
Oidrettype,boolhaspolyarg)
91+
init_execution_state(List*queryTree_list)
9592
{
96-
execution_state*firstes;
97-
execution_state*preves;
98-
List*queryTree_list,
99-
*qtl_item;
100-
101-
queryTree_list=pg_parse_and_rewrite(src,argOidVect,nargs);
102-
103-
/*
104-
* If the function has any arguments declared as polymorphic types,
105-
* then it wasn't type-checked at definition time; must do so now.
106-
*/
107-
if (haspolyarg)
108-
check_sql_fn_retval(rettype,get_typtype(rettype),queryTree_list);
109-
110-
firstes=NULL;
111-
preves=NULL;
93+
execution_state*firstes=NULL;
94+
execution_state*preves=NULL;
95+
List*qtl_item;
11296

11397
foreach(qtl_item,queryTree_list)
11498
{
@@ -151,6 +135,7 @@ init_sql_fcache(FmgrInfo *finfo)
151135
boolhaspolyarg;
152136
char*src;
153137
intnargs;
138+
List*queryTree_list;
154139
Datumtmp;
155140
boolisNull;
156141

@@ -191,15 +176,17 @@ init_sql_fcache(FmgrInfo *finfo)
191176
typeStruct= (Form_pg_type)GETSTRUCT(typeTuple);
192177

193178
/*
194-
* get the type length and by-value flag from the type tuple
179+
* get the type length and by-value flag from the type tuple; also
180+
* do a preliminary check for returnsTuple (this may prove inaccurate,
181+
* see below).
195182
*/
196183
fcache->typlen=typeStruct->typlen;
197184
fcache->typbyval=typeStruct->typbyval;
198185
fcache->returnsTuple= (typeStruct->typtype=='c'||
199186
rettype==RECORDOID);
200187

201188
/*
202-
* Parse andplan the queries.We need the argument type info to pass
189+
* Parse andrewrite the queries.We need the argument type info to pass
203190
* to the parser.
204191
*/
205192
nargs=procedureStruct->pronargs;
@@ -242,8 +229,25 @@ init_sql_fcache(FmgrInfo *finfo)
242229
elog(ERROR,"null prosrc for function %u",foid);
243230
src=DatumGetCString(DirectFunctionCall1(textout,tmp));
244231

245-
fcache->func_state=init_execution_state(src,argOidVect,nargs,
246-
rettype,haspolyarg);
232+
queryTree_list=pg_parse_and_rewrite(src,argOidVect,nargs);
233+
234+
/*
235+
* If the function has any arguments declared as polymorphic types,
236+
* then it wasn't type-checked at definition time; must do so now.
237+
*
238+
* Also, force a type-check if the declared return type is a rowtype;
239+
* we need to find out whether we are actually returning the whole
240+
* tuple result, or just regurgitating a rowtype expression result.
241+
* In the latter case we clear returnsTuple because we need not act
242+
* different from the scalar result case.
243+
*/
244+
if (haspolyarg||fcache->returnsTuple)
245+
fcache->returnsTuple=check_sql_fn_retval(rettype,
246+
get_typtype(rettype),
247+
queryTree_list);
248+
249+
/* Finally, plan the queries */
250+
fcache->func_state=init_execution_state(queryTree_list);
247251

248252
pfree(src);
249253

‎src/backend/optimizer/util/clauses.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.168 2004/04/0219:06:57 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.169 2004/04/0223:14:08 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -1992,8 +1992,8 @@ inline_function(Oid funcid, Oid result_type, List *args,
19921992
* probably not important, but let's be careful.)
19931993
*/
19941994
if (polymorphic)
1995-
check_sql_fn_retval(result_type,get_typtype(result_type),
1996-
querytree_list);
1995+
(void)check_sql_fn_retval(result_type,get_typtype(result_type),
1996+
querytree_list);
19971997

19981998
/*
19991999
* Additional validity checks on the expression. It mustn't return a

‎src/include/catalog/pg_proc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.323 2004/04/01 21:28:45 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.324 2004/04/02 23:14:08 tgl Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3560,7 +3560,7 @@ extern Oid ProcedureCreate(const char *procedureName,
35603560
constOid*parameterTypes,
35613561
constchar*parameterNames[]);
35623562

3563-
externvoidcheck_sql_fn_retval(Oidrettype,charfn_typtype,
3563+
externboolcheck_sql_fn_retval(Oidrettype,charfn_typtype,
35643564
List*queryTreeList);
35653565

35663566
externboolfunction_parse_error_transpose(constchar*prosrc);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp