diff options
Diffstat (limited to 'src/backend/utils/fmgr/fmgr.c')
| -rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 82dbb8e970..de09419542 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.122 2008/08/25 22:42:34 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.123 2008/12/28 18:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2218,6 +2218,7 @@ pg_detoast_datum_packed(struct varlena * datum) * * These are needed by polymorphic functions, which accept multiple possible * input types and need help from the parser to know what they've got. + * Also, some functions might be interested in whether a parameter is constant. *------------------------------------------------------------------------- */ @@ -2288,6 +2289,8 @@ get_call_expr_argtype(Node *expr, int argnum) args = list_make1(((ArrayCoerceExpr *) expr)->arg); else if (IsA(expr, NullIfExpr)) args = ((NullIfExpr *) expr)->args; + else if (IsA(expr, WindowFunc)) + args = ((WindowFunc *) expr)->args; else return InvalidOid; @@ -2310,3 +2313,73 @@ get_call_expr_argtype(Node *expr, int argnum) return argtype; } + +/* + * Find out whether a specific function argument is constant for the + * duration of a query + * + * Returns false if information is not available + */ +bool +get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum) +{ + /* + * can't return anything useful if we have no FmgrInfo or if its fn_expr + * node has not been initialized + */ + if (!flinfo || !flinfo->fn_expr) + return false; + + return get_call_expr_arg_stable(flinfo->fn_expr, argnum); +} + +/* + * Find out whether a specific function argument is constant for the + * duration of a query, but working from the calling expression tree + * + * Returns false if information is not available + */ +bool +get_call_expr_arg_stable(Node *expr, int argnum) +{ + List *args; + Node *arg; + + if (expr == NULL) + return false; + + if (IsA(expr, FuncExpr)) + args = ((FuncExpr *) expr)->args; + else if (IsA(expr, OpExpr)) + args = ((OpExpr *) expr)->args; + else if (IsA(expr, DistinctExpr)) + args = ((DistinctExpr *) expr)->args; + else if (IsA(expr, ScalarArrayOpExpr)) + args = ((ScalarArrayOpExpr *) expr)->args; + else if (IsA(expr, ArrayCoerceExpr)) + args = list_make1(((ArrayCoerceExpr *) expr)->arg); + else if (IsA(expr, NullIfExpr)) + args = ((NullIfExpr *) expr)->args; + else if (IsA(expr, WindowFunc)) + args = ((WindowFunc *) expr)->args; + else + return false; + + if (argnum < 0 || argnum >= list_length(args)) + return false; + + arg = (Node *) list_nth(args, argnum); + + /* + * Either a true Const or an external Param will have a value that + * doesn't change during the execution of the query. In future we + * might want to consider other cases too, e.g. now(). + */ + if (IsA(arg, Const)) + return true; + if (IsA(arg, Param) && + ((Param *) arg)->paramkind == PARAM_EXTERN) + return true; + + return false; +} |
