diff --git a/src/bin/pg_dump/pg_dump.cpp b/src/bin/pg_dump/pg_dump.cpp index 3907a198cb2ef65228f58ed2e7195b5f176bc7ac..50da15e321fe109066eea889cd09e370456b58f3 100644 --- a/src/bin/pg_dump/pg_dump.cpp +++ b/src/bin/pg_dump/pg_dump.cpp @@ -13072,6 +13072,8 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) PQExpBuffer delqry; PQExpBuffer labelq; PQExpBuffer asPart; + PQExpBuffer headWithDefault; + PQExpBuffer headWithoutDefault; PGresult* res = NULL; PGresult* defres = NULL; char* funcsig = NULL; /* identity signature */ @@ -13096,6 +13098,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) char* procost = NULL; char* prorows = NULL; char* lanname = NULL; + char* selfloop = NULL; char* fencedmode = NULL; /*Fenced UDF add*/ char* proKind = NULL; char* proshippable = NULL; @@ -13118,6 +13121,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) bool hasProargsrc = false; bool isNullProargsrc = false; bool addDelimiter = false; + bool isNullSelfloop = false; const char *funcKind; ArchiveHandle* AH = (ArchiveHandle*)fout; @@ -13134,6 +13138,8 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) labelq = createPQExpBuffer(); asPart = createPQExpBuffer(); definerquery = createPQExpBuffer(); + headWithDefault = createPQExpBuffer(); + headWithoutDefault = createPQExpBuffer(); /* Set proper schema search path so type references list correctly */ selectSourceSchema(fout, finfo->dobj.nmspace->dobj.name); @@ -13159,7 +13165,8 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) "%s, " "%s, " "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " - "%s " + "%s, " + "(SELECT 1 FROM pg_depend WHERE objid = oid AND objid = refobjid AND refclassid = 1255 LIMIT 1) AS selfloop " "FROM pg_catalog.pg_proc " "WHERE oid = '%u'::pg_catalog.oid", isHasFencedmode ? "fencedmode" : "NULL AS fencedmode", @@ -13186,6 +13193,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig")); procost = PQgetvalue(res, 0, PQfnumber(res, "procost")); prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows")); + selfloop = PQgetvalue(res, 0, PQfnumber(res, "selfloop")); lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname")); fencedmode = PQgetvalue(res, 0, PQfnumber(res, "fencedmode")); proshippable = PQgetvalue(res, 0, PQfnumber(res, "proshippable")); @@ -13215,6 +13223,8 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) destroyPQExpBuffer(labelq); destroyPQExpBuffer(asPart); destroyPQExpBuffer(definerquery); + destroyPQExpBuffer(headWithDefault); + destroyPQExpBuffer(headWithoutDefault); return; } } @@ -13339,22 +13349,42 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) appendPQExpBuffer(delqry, "DROP %s IF EXISTS %s.%s%s;\n", funcKind, fmtId(finfo->dobj.nmspace->dobj.name), funcsig, if_cascade); + isNullSelfloop = (selfloop == NULL || selfloop[0] == '\0'); + + if (!isNullSelfloop) { + if (addDelimiter && IsPlainFormat()) { + appendPQExpBuffer(headWithoutDefault, "delimiter //\n"); + } + + if ((gdatcompatibility != NULL) && strcmp(gdatcompatibility, B_FORMAT) == 0) { + appendPQExpBuffer(headWithoutDefault, "CREATE DEFINER = \"%s\" %s %s ", definer, funcKind, funcsig); + } else { + appendPQExpBuffer(headWithoutDefault, "CREATE %s %s ", funcKind, funcsig); + } + } + if (addDelimiter && IsPlainFormat()) { - appendPQExpBuffer(q, "delimiter //\n"); + appendPQExpBuffer(headWithDefault, "delimiter //\n"); } if ((gdatcompatibility != NULL) && strcmp(gdatcompatibility, B_FORMAT) == 0) { - appendPQExpBuffer(q, "CREATE DEFINER = \"%s\" %s %s ", definer, funcKind, funcfullsig); + if (isNullSelfloop) + appendPQExpBuffer(headWithDefault, "CREATE DEFINER = \"%s\" %s %s ", definer, funcKind, funcfullsig); + else + appendPQExpBuffer(headWithDefault, "CREATE OR REPLACE %s %s ", funcKind, funcfullsig); PQclear(defres); } else { - appendPQExpBuffer(q, "CREATE %s %s ", funcKind, funcfullsig); + if (isNullSelfloop) + appendPQExpBuffer(headWithDefault, "CREATE %s %s ", funcKind, funcfullsig); + else + appendPQExpBuffer(headWithDefault, "CREATE OR REPLACE %s %s ", funcKind, funcfullsig); } if (isProcedure) { /* For procedure, no return type, do nothing */ } else if (funcresult != NULL) { - if (!isNullProargsrc) { + if (!isNullProargsrc && !addDelimiter) { appendPQExpBuffer(q, "RETURN %s", funcresult); } else { appendPQExpBuffer(q, "RETURNS %s", funcresult); @@ -13482,6 +13512,12 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) appendPQExpBuffer(q, "delimiter ;\n"); } + if (isNullSelfloop) { + appendPQExpBuffer(headWithDefault, "%s", q->data); + } else { + appendPQExpBuffer(headWithoutDefault, "%s\n%s%s", q->data, headWithDefault->data, q->data); + } + ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId, @@ -13492,7 +13528,7 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) false, funcKind, SECTION_PRE_DATA, - q->data, + isNullSelfloop ? headWithDefault->data : headWithoutDefault->data, delqry->data, NULL, NULL, @@ -13525,6 +13561,8 @@ static void dumpFunc(Archive* fout, FuncInfo* finfo) destroyPQExpBuffer(labelq); destroyPQExpBuffer(asPart); destroyPQExpBuffer(definerquery); + destroyPQExpBuffer(headWithDefault); + destroyPQExpBuffer(headWithoutDefault); GS_FREE(funcsig); GS_FREE(funcfullsig); diff --git a/src/bin/pg_dump/pg_dump_sort.cpp b/src/bin/pg_dump/pg_dump_sort.cpp index b6359104b31b597c5df0f50374bed2d142f5f133..79ccd69327edeedce8efdfe95587e3c5e2fc992a 100644 --- a/src/bin/pg_dump/pg_dump_sort.cpp +++ b/src/bin/pg_dump/pg_dump_sort.cpp @@ -951,7 +951,7 @@ static void repairDependencyLoop(DumpableObject** loop, int nLoop) * dependency data, so we can't see that here.) */ if (nLoop == 1) { - if (loop[0]->objType == DO_TABLE) { + if (loop[0]->objType == DO_TABLE || loop[0]->objType == DO_FUNC) { removeObjectDependency(loop[0], loop[0]->dumpId); return; }