diff options
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r-- | src/backend/commands/functioncmds.c | 110 |
1 files changed, 103 insertions, 7 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 15608140d73..2971add22a6 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.81 2007/01/05 22:19:26 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.82 2007/01/22 01:35:20 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -273,7 +273,9 @@ static bool compute_common_attribute(DefElem *defel, DefElem **volatility_item, DefElem **strict_item, - DefElem **security_item) + DefElem **security_item, + DefElem **cost_item, + DefElem **rows_item) { if (strcmp(defel->defname, "volatility") == 0) { @@ -296,6 +298,20 @@ compute_common_attribute(DefElem *defel, *security_item = defel; } + else if (strcmp(defel->defname, "cost") == 0) + { + if (*cost_item) + goto duplicate_error; + + *cost_item = defel; + } + else if (strcmp(defel->defname, "rows") == 0) + { + if (*rows_item) + goto duplicate_error; + + *rows_item = defel; + } else return false; @@ -337,7 +353,9 @@ compute_attributes_sql_style(List *options, char **language, char *volatility_p, bool *strict_p, - bool *security_definer) + bool *security_definer, + float4 *procost, + float4 *prorows) { ListCell *option; DefElem *as_item = NULL; @@ -345,6 +363,8 @@ compute_attributes_sql_style(List *options, DefElem *volatility_item = NULL; DefElem *strict_item = NULL; DefElem *security_item = NULL; + DefElem *cost_item = NULL; + DefElem *rows_item = NULL; foreach(option, options) { @@ -369,7 +389,9 @@ compute_attributes_sql_style(List *options, else if (compute_common_attribute(defel, &volatility_item, &strict_item, - &security_item)) + &security_item, + &cost_item, + &rows_item)) { /* recognized common option */ continue; @@ -407,6 +429,22 @@ compute_attributes_sql_style(List *options, *strict_p = intVal(strict_item->arg); if (security_item) *security_definer = intVal(security_item->arg); + if (cost_item) + { + *procost = defGetNumeric(cost_item); + if (*procost <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("COST must be positive"))); + } + if (rows_item) + { + *prorows = defGetNumeric(rows_item); + if (*prorows <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("ROWS must be positive"))); + } } @@ -519,6 +557,8 @@ CreateFunction(CreateFunctionStmt *stmt) bool isStrict, security; char volatility; + float4 procost; + float4 prorows; HeapTuple languageTuple; Form_pg_language languageStruct; List *as_clause; @@ -537,10 +577,14 @@ CreateFunction(CreateFunctionStmt *stmt) isStrict = false; security = false; volatility = PROVOLATILE_VOLATILE; + procost = -1; /* indicates not set */ + prorows = -1; /* indicates not set */ /* override attributes from explicit list */ compute_attributes_sql_style(stmt->options, - &as_clause, &language, &volatility, &isStrict, &security); + &as_clause, &language, + &volatility, &isStrict, &security, + &procost, &prorows); /* Convert language name to canonical case */ languageName = case_translate_language_name(language); @@ -646,6 +690,32 @@ CreateFunction(CreateFunctionStmt *stmt) } /* + * Set default values for COST and ROWS depending on other parameters; + * reject ROWS if it's not returnsSet. NB: pg_dump knows these default + * values, keep it in sync if you change them. + */ + if (procost < 0) + { + /* SQL and PL-language functions are assumed more expensive */ + if (languageOid == INTERNALlanguageId || + languageOid == ClanguageId) + procost = 1; + else + procost = 100; + } + if (prorows < 0) + { + if (returnsSet) + prorows = 1000; + else + prorows = 0; /* dummy value if not returnsSet */ + } + else if (!returnsSet) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("ROWS is not applicable when function does not return a set"))); + + /* * And now that we have all the parameters, and know we're permitted to do * so, go ahead and create the function. */ @@ -665,7 +735,9 @@ CreateFunction(CreateFunctionStmt *stmt) parameterTypes, PointerGetDatum(allParameterTypes), PointerGetDatum(parameterModes), - PointerGetDatum(parameterNames)); + PointerGetDatum(parameterNames), + procost, + prorows); } @@ -1012,6 +1084,8 @@ AlterFunction(AlterFunctionStmt *stmt) DefElem *volatility_item = NULL; DefElem *strict_item = NULL; DefElem *security_def_item = NULL; + DefElem *cost_item = NULL; + DefElem *rows_item = NULL; rel = heap_open(ProcedureRelationId, RowExclusiveLock); @@ -1046,7 +1120,9 @@ AlterFunction(AlterFunctionStmt *stmt) if (compute_common_attribute(defel, &volatility_item, &strict_item, - &security_def_item) == false) + &security_def_item, + &cost_item, + &rows_item) == false) elog(ERROR, "option \"%s\" not recognized", defel->defname); } @@ -1056,6 +1132,26 @@ AlterFunction(AlterFunctionStmt *stmt) procForm->proisstrict = intVal(strict_item->arg); if (security_def_item) procForm->prosecdef = intVal(security_def_item->arg); + if (cost_item) + { + procForm->procost = defGetNumeric(cost_item); + if (procForm->procost <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("COST must be positive"))); + } + if (rows_item) + { + procForm->prorows = defGetNumeric(rows_item); + if (procForm->prorows <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("ROWS must be positive"))); + if (!procForm->proretset) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("ROWS is not applicable when function does not return a set"))); + } /* Do the update */ simple_heap_update(rel, &tup->t_self, tup); |