>From 5e6d387d583c9f434ed8e58107043b5f1e2f9e89 Mon Sep 17 00:00:00 2001 From: Petr Jelinek Date: Fri, 8 Aug 2014 14:55:47 +0200 Subject: [PATCH 27/42] deparse: Support ALTER FUNCTION --- src/backend/tcop/deparse_utility.c | 109 ++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c index a432a38..6110827 100644 --- a/src/backend/tcop/deparse_utility.c +++ b/src/backend/tcop/deparse_utility.c @@ -2957,6 +2957,113 @@ deparse_CreateFunction(Oid objectId, Node *parsetree) } /* + * deparse_AlterFunctionStmt + * Deparse a AlterFunctionStmt (ALTER FUNCTION) + * + * Given a function OID and the parsetree that created it, return the JSON + * blob representing the alter command. + * + * XXX this is missing the per-function custom-GUC thing. + */ +static ObjTree * +deparse_AlterFunction(Oid objectId, Node *parsetree) +{ + AlterFunctionStmt *node = (AlterFunctionStmt *) parsetree; + ObjTree *alterFunc; + ObjTree *sign; + HeapTuple procTup; + Form_pg_proc procForm; + List *params; + List *elems = NIL; + ListCell *cell; + int i; + + /* get the pg_proc tuple */ + procTup = SearchSysCache1(PROCOID, objectId); + if (!HeapTupleIsValid(procTup)) + elog(ERROR, "cache lookup failure for function with OID %u", + objectId); + procForm = (Form_pg_proc) GETSTRUCT(procTup); + + alterFunc = new_objtree_VA("ALTER FUNCTION %{signature}s %{definition: }s", 0); + + sign = new_objtree_VA("%{identity}D(%{arguments:, }s)", 0); + + params = NIL; + + /* + * ALTER FUNCTION does not change signature so we can use catalog + * to get input type Oids. + */ + for (i = 0; i < procForm->pronargs; i++) + { + ObjTree *tmp = new_objtree_VA("%{type}T", 0); + + append_object_object(tmp, "type", + new_objtree_for_type(procForm->proargtypes.values[i], -1)); + params = lappend(params, new_object_object(tmp)); + } + + append_array_object(sign, "arguments", params); + append_object_object(sign, "identity", + new_objtree_for_qualname_id(ProcedureRelationId, + objectId)); + append_object_object(alterFunc, "signature", sign); + + foreach(cell, node->actions) + { + DefElem *defel = (DefElem *) lfirst(cell); + ObjTree *tmp = NULL; + + if (strcmp(defel->defname, "volatility") == 0) + { + tmp = new_objtree_VA(strVal(defel->arg), 0); + } + else if (strcmp(defel->defname, "strict") == 0) + { + tmp = new_objtree_VA(intVal(defel->arg) ? + "RETURNS NULL ON NULL INPUT" : + "CALLED ON NULL INPUT", 0); + } + else if (strcmp(defel->defname, "security") == 0) + { + tmp = new_objtree_VA(intVal(defel->arg) ? + "SECURITY DEFINER" : "SECURITY INVOKER", 0); + } + else if (strcmp(defel->defname, "leakproof") == 0) + { + tmp = new_objtree_VA(intVal(defel->arg) ? + "LEAKPROOF" : "", 0); + } + else if (strcmp(defel->defname, "cost") == 0) + { + tmp = new_objtree_VA("COST %{cost}n", 1, + "cost", ObjTypeFloat, + defGetNumeric(defel)); + } + else if (strcmp(defel->defname, "rows") == 0) + { + tmp = new_objtree_VA("ROWS %{rows}n", 0); + if (defGetNumeric(defel) == 0) + append_bool_object(tmp, "present", false); + else + append_float_object(tmp, "rows", + defGetNumeric(defel)); + } + else if (strcmp(defel->defname, "set") == 0) + elog(ERROR, "unimplemented deparse of ALTER FUNCTION SET"); + + elems = lappend(elems, new_object_object(tmp)); + } + + append_array_object(alterFunc, "definition", elems); + + ReleaseSysCache(procTup); + + return alterFunc; +} + +/* * Return the given object type as a string. */ static const char * @@ -4807,7 +4914,7 @@ deparse_simple_command(StashedCommand *cmd) break; case T_AlterFunctionStmt: - command = NULL; + command = deparse_AlterFunction(objectId, parsetree); break; case T_RuleStmt: -- 2.1.4