*** pgsql/src/backend/commands/functioncmds.c 2008/12/04 17:51:26 1.102 --- pgsql/src/backend/commands/functioncmds.c 2008/12/18 18:20:33 1.103 *************** *** 10,16 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.101 2008/11/02 01:45:27 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the --- 10,16 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.102 2008/12/04 17:51:26 petere Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the *************** *** 48,58 **** #include "commands/defrem.h" #include "commands/proclang.h" #include "miscadmin.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" #include "parser/parse_type.h" - #include "parser/parse_utilcmd.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" --- 48,58 ---- #include "commands/defrem.h" #include "commands/proclang.h" #include "miscadmin.h" + #include "optimizer/var.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" *************** compute_return_type(TypeName *returnType *** 162,174 **** */ static void examine_parameter_list(List *parameters, Oid languageOid, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, ! Oid *requiredResultType, ! const char *queryString) { int parameterCount = list_length(parameters); Oid *inTypes; --- 162,174 ---- */ static void examine_parameter_list(List *parameters, Oid languageOid, + const char *queryString, oidvector **parameterTypes, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **parameterDefaults, ! Oid *requiredResultType) { int parameterCount = list_length(parameters); Oid *inTypes; *************** examine_parameter_list(List *parameters, *** 179,187 **** int outCount = 0; int varCount = 0; bool have_names = false; ListCell *x; int i; - bool have_defaults = false; ParseState *pstate; *requiredResultType = InvalidOid; /* default result */ --- 179,187 ---- int outCount = 0; int varCount = 0; bool have_names = false; + bool have_defaults = false; ListCell *x; int i; ParseState *pstate; *requiredResultType = InvalidOid; /* default result */ *************** examine_parameter_list(List *parameters, *** 192,197 **** --- 192,198 ---- paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum)); *parameterDefaults = NIL; + /* may need a pstate for parse analysis of default exprs */ pstate = make_parsestate(NULL); pstate->p_sourcetext = queryString; *************** examine_parameter_list(List *parameters, *** 201,206 **** --- 202,208 ---- { FunctionParameter *fp = (FunctionParameter *) lfirst(x); TypeName *t = fp->argType; + bool isinput = false; Oid toid; Type typtup; *************** examine_parameter_list(List *parameters, *** 247,252 **** --- 249,255 ---- (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("VARIADIC parameter must be the last input parameter"))); inTypes[inCount++] = toid; + isinput = true; } /* handle output parameters */ *************** examine_parameter_list(List *parameters, *** 288,311 **** if (fp->defexpr) { ! if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_INOUT) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), ! errmsg("only IN and INOUT parameters can have default values"))); ! *parameterDefaults = lappend(*parameterDefaults, ! coerce_to_specific_type(NULL, ! transformExpr(pstate, fp->defexpr), ! toid, ! "DEFAULT")); have_defaults = true; } else { ! if (have_defaults) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), ! errmsg("parameter without default value specified after parameter with default value"))); } i++; --- 291,336 ---- if (fp->defexpr) { ! Node *def; ! ! if (!isinput) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), ! errmsg("only input parameters can have default values"))); ! ! def = transformExpr(pstate, fp->defexpr); ! def = coerce_to_specific_type(pstate, def, toid, "DEFAULT"); ! ! /* ! * Make sure no variables are referred to. ! */ ! if (list_length(pstate->p_rtable) != 0 || ! contain_var_clause(def)) ! ereport(ERROR, ! (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), ! errmsg("cannot use table references in parameter default value"))); ! ! /* ! * No subplans or aggregates, either... ! */ ! if (pstate->p_hasSubLinks) ! ereport(ERROR, ! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("cannot use subquery in parameter default value"))); ! if (pstate->p_hasAggs) ! ereport(ERROR, ! (errcode(ERRCODE_GROUPING_ERROR), ! errmsg("cannot use aggregate function in parameter default value"))); ! *parameterDefaults = lappend(*parameterDefaults, def); have_defaults = true; } else { ! if (isinput && have_defaults) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), ! errmsg("input parameters after one with a default value must also have defaults"))); } i++; *************** CreateFunction(CreateFunctionStmt *stmt, *** 704,709 **** --- 729,735 ---- ArrayType *allParameterTypes; ArrayType *parameterModes; ArrayType *parameterNames; + List *parameterDefaults; Oid requiredResultType; bool isStrict, security; *************** CreateFunction(CreateFunctionStmt *stmt, *** 714,720 **** HeapTuple languageTuple; Form_pg_language languageStruct; List *as_clause; - List *defaults = NULL; /* Convert list of names to a name and namespace */ namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname, --- 740,745 ---- *************** CreateFunction(CreateFunctionStmt *stmt, *** 783,796 **** * Convert remaining parameters of CREATE to form wanted by * ProcedureCreate. */ ! examine_parameter_list(stmt->parameters, languageOid, ¶meterTypes, &allParameterTypes, ¶meterModes, ¶meterNames, ! &defaults, ! &requiredResultType, ! queryString); if (stmt->returnType) { --- 808,820 ---- * Convert remaining parameters of CREATE to form wanted by * ProcedureCreate. */ ! examine_parameter_list(stmt->parameters, languageOid, queryString, ¶meterTypes, &allParameterTypes, ¶meterModes, ¶meterNames, ! ¶meterDefaults, ! &requiredResultType); if (stmt->returnType) { *************** CreateFunction(CreateFunctionStmt *stmt, *** 871,880 **** PointerGetDatum(allParameterTypes), PointerGetDatum(parameterModes), PointerGetDatum(parameterNames), PointerGetDatum(proconfig), procost, ! prorows, ! defaults); } --- 895,904 ---- PointerGetDatum(allParameterTypes), PointerGetDatum(parameterModes), PointerGetDatum(parameterNames), + parameterDefaults, PointerGetDatum(proconfig), procost, ! prorows); }