mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Dept. of second thoughts: supporting inlining of polymorphic SQL functions
takes only a few more lines of code than preventing it, so might as well support it.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.143 2003/07/01 00:04:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.144 2003/07/01 19:07:02 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -30,6 +30,7 @@
|
|||||||
#include "optimizer/var.h"
|
#include "optimizer/var.h"
|
||||||
#include "parser/analyze.h"
|
#include "parser/analyze.h"
|
||||||
#include "parser/parse_clause.h"
|
#include "parser/parse_clause.h"
|
||||||
|
#include "parser/parse_expr.h"
|
||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
@ -1719,6 +1720,8 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
{
|
{
|
||||||
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
|
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
|
||||||
char result_typtype;
|
char result_typtype;
|
||||||
|
bool polymorphic = false;
|
||||||
|
Oid argtypes[FUNC_MAX_ARGS];
|
||||||
char *src;
|
char *src;
|
||||||
Datum tmp;
|
Datum tmp;
|
||||||
bool isNull;
|
bool isNull;
|
||||||
@ -1731,7 +1734,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
int *usecounts;
|
int *usecounts;
|
||||||
List *arg;
|
List *arg;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forget it if the function is not SQL-language or has other
|
* Forget it if the function is not SQL-language or has other
|
||||||
@ -1743,17 +1745,15 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
funcform->pronargs != length(args))
|
funcform->pronargs != length(args))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Forget it if declared return type is not base or domain */
|
/* Forget it if declared return type is not base, domain, or polymorphic */
|
||||||
result_typtype = get_typtype(funcform->prorettype);
|
result_typtype = get_typtype(funcform->prorettype);
|
||||||
if (result_typtype != 'b' &&
|
if (result_typtype != 'b' &&
|
||||||
result_typtype != 'd')
|
result_typtype != 'd')
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Forget it if any declared argument type is polymorphic */
|
|
||||||
for (j = 0; j < funcform->pronargs; j++)
|
|
||||||
{
|
{
|
||||||
if (funcform->proargtypes[j] == ANYARRAYOID ||
|
if (funcform->prorettype == ANYARRAYOID ||
|
||||||
funcform->proargtypes[j] == ANYELEMENTOID)
|
funcform->prorettype == ANYELEMENTOID)
|
||||||
|
polymorphic = true;
|
||||||
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1765,6 +1765,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
|
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Check for polymorphic arguments, and substitute actual arg types */
|
||||||
|
memcpy(argtypes, funcform->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
|
||||||
|
for (i = 0; i < funcform->pronargs; i++)
|
||||||
|
{
|
||||||
|
if (argtypes[i] == ANYARRAYOID ||
|
||||||
|
argtypes[i] == ANYELEMENTOID)
|
||||||
|
{
|
||||||
|
polymorphic = true;
|
||||||
|
argtypes[i] = exprType((Node *) nth(i, args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a temporary memory context, so that we don't leak all the
|
* Make a temporary memory context, so that we don't leak all the
|
||||||
* stuff that parsing might create.
|
* stuff that parsing might create.
|
||||||
@ -1797,8 +1809,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
querytree_list = parse_analyze(lfirst(raw_parsetree_list),
|
querytree_list = parse_analyze(lfirst(raw_parsetree_list),
|
||||||
funcform->proargtypes,
|
argtypes, funcform->pronargs);
|
||||||
funcform->pronargs);
|
|
||||||
|
|
||||||
if (length(querytree_list) != 1)
|
if (length(querytree_list) != 1)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1829,6 +1840,18 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
|
|
||||||
newexpr = (Node *) ((TargetEntry *) lfirst(querytree->targetList))->expr;
|
newexpr = (Node *) ((TargetEntry *) lfirst(querytree->targetList))->expr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the function has any arguments declared as polymorphic types,
|
||||||
|
* then it wasn't type-checked at definition time; must do so now.
|
||||||
|
* (This will raise an error if wrong, but that's okay since the
|
||||||
|
* function would fail at runtime anyway. Note we do not try this
|
||||||
|
* until we have verified that no rewriting was needed; that's probably
|
||||||
|
* not important, but let's be careful.)
|
||||||
|
*/
|
||||||
|
if (polymorphic)
|
||||||
|
check_sql_fn_retval(result_type, get_typtype(result_type),
|
||||||
|
querytree_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Additional validity checks on the expression. It mustn't return a
|
* Additional validity checks on the expression. It mustn't return a
|
||||||
* set, and it mustn't be more volatile than the surrounding function
|
* set, and it mustn't be more volatile than the surrounding function
|
||||||
|
Reference in New Issue
Block a user