diff options
Diffstat (limited to 'src/bin/pg_dump')
-rw-r--r-- | src/bin/pg_dump/common.c | 5 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 172 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.h | 9 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump_sort.c | 11 |
4 files changed, 195 insertions, 2 deletions
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index f798b15e3c4..1acd91ab444 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -98,6 +98,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) int numProcLangs; int numCasts; int numTransforms; + int numAccessMethods; int numOpclasses; int numOpfamilies; int numConversions; @@ -169,6 +170,10 @@ getSchemaData(Archive *fout, int *numTablesPtr) oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo)); if (g_verbose) + write_msg(NULL, "reading user-defined access methods\n"); + getAccessMethods(fout, &numAccessMethods); + + if (g_verbose) write_msg(NULL, "reading user-defined operator classes\n"); getOpclasses(fout, &numOpclasses); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 64c2673f9a5..b3ef201a3ae 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -45,6 +45,7 @@ #include "access/attnum.h" #include "access/sysattr.h" #include "access/transam.h" +#include "catalog/pg_am.h" #include "catalog/pg_cast.h" #include "catalog/pg_class.h" #include "catalog/pg_default_acl.h" @@ -173,6 +174,7 @@ static void dumpFunc(Archive *fout, FuncInfo *finfo); static void dumpCast(Archive *fout, CastInfo *cast); static void dumpTransform(Archive *fout, TransformInfo *transform); static void dumpOpr(Archive *fout, OprInfo *oprinfo); +static void dumpAccessMethod(Archive *fout, AccessMethodInfo *oprinfo); static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo); static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo); static void dumpCollation(Archive *fout, CollInfo *convinfo); @@ -1469,6 +1471,26 @@ selectDumpableProcLang(ProcLangInfo *plang, DumpOptions *dopt) } /* + * selectDumpableAccessMethod: policy-setting subroutine + * Mark an access method as to be dumped or not + * + * Access methods do not belong to any particular namespace. To identify + * built-in access methods, we must resort to checking whether the + * method's OID is in the range reserved for initdb. + */ +static void +selectDumpableAccessMethod(AccessMethodInfo *method, DumpOptions *dopt) +{ + if (checkExtensionMembership(&method->dobj, dopt)) + return; /* extension membership overrides all else */ + + if (method->dobj.catId.oid < (Oid) FirstNormalObjectId) + method->dobj.dump = false; + else + method->dobj.dump = dopt->include_everything; +} + +/* * selectDumpableExtension: policy-setting subroutine * Mark an extension as to be dumped or not * @@ -4101,6 +4123,84 @@ getConversions(Archive *fout, int *numConversions) } /* + * getAccessMethods: + * read all user-defined access methods in the system catalogs and return + * them in the AccessMethodInfo* structure + * + * numAccessMethods is set to the number of access methods read in + */ +AccessMethodInfo * +getAccessMethods(Archive *fout, int *numAccessMethods) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + AccessMethodInfo *aminfo; + int i_tableoid; + int i_oid; + int i_amname; + int i_amhandler; + int i_amtype; + + /* Before 9.6, there are no user-defined access methods */ + if (fout->remoteVersion < 90600) + { + *numAccessMethods = 0; + return NULL; + } + + query = createPQExpBuffer(); + + /* Make sure we are in proper schema */ + selectSourceSchema(fout, "pg_catalog"); + + /* + * Select only user-defined access methods assuming all built-in access + * methods have oid < 10000. + */ + appendPQExpBuffer(query, "SELECT tableoid, oid, amname, amtype, " + "amhandler::pg_catalog.regproc AS amhandler " + "FROM pg_am"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numAccessMethods = ntups; + + aminfo = (AccessMethodInfo *) pg_malloc(ntups * sizeof(AccessMethodInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_amname = PQfnumber(res, "amname"); + i_amhandler = PQfnumber(res, "amhandler"); + i_amtype = PQfnumber(res, "amtype"); + + for (i = 0; i < ntups; i++) + { + aminfo[i].dobj.objType = DO_ACCESS_METHOD; + aminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + aminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&aminfo[i].dobj); + aminfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_amname)); + aminfo[i].dobj.namespace = NULL; + aminfo[i].amhandler = pg_strdup(PQgetvalue(res, i, i_amhandler)); + aminfo[i].amtype = *(PQgetvalue(res, i, i_amtype)); + + /* Decide whether we want to dump it */ + selectDumpableAccessMethod(&(aminfo[i]), dopt); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return aminfo; +} + + +/* * getOpclasses: * read all opclasses in the system catalogs and return them in the * OpclassInfo* structure @@ -8408,6 +8508,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj) case DO_OPERATOR: dumpOpr(fout, (OprInfo *) dobj); break; + case DO_ACCESS_METHOD: + dumpAccessMethod(fout, (AccessMethodInfo *) dobj); + break; case DO_OPCLASS: dumpOpclass(fout, (OpclassInfo *) dobj); break; @@ -11446,6 +11549,74 @@ convertTSFunction(Archive *fout, Oid funcOid) return result; } +/* + * dumpAccessMethod + * write out a single access method definition + */ +static void +dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer labelq; + char *qamname; + + /* Skip if not to be dumped */ + if (!aminfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + labelq = createPQExpBuffer(); + + qamname = pg_strdup(fmtId(aminfo->dobj.name)); + + appendPQExpBuffer(q, "CREATE ACCESS METHOD %s ", qamname); + + switch (aminfo->amtype) + { + case AMTYPE_INDEX: + appendPQExpBuffer(q, "TYPE INDEX "); + break; + default: + write_msg(NULL, "WARNING: invalid type %c of access method %s\n", + aminfo->amtype, qamname); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(labelq); + return; + } + + appendPQExpBuffer(q, "HANDLER %s;\n", aminfo->amhandler); + + appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n", + qamname); + + appendPQExpBuffer(labelq, "ACCESS METHOD %s", + qamname); + + ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId, + aminfo->dobj.name, + NULL, + NULL, + "", + false, "ACCESS METHOD", SECTION_PRE_DATA, + q->data, delq->data, NULL, + NULL, 0, + NULL, NULL); + + /* Dump Access Method Comments */ + dumpComment(fout, labelq->data, + NULL, "", + aminfo->dobj.catId, 0, aminfo->dobj.dumpId); + + free(qamname); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(labelq); +} /* * dumpOpclass @@ -16227,6 +16398,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs, case DO_FUNC: case DO_AGG: case DO_OPERATOR: + case DO_ACCESS_METHOD: case DO_OPCLASS: case DO_OPFAMILY: case DO_COLLATION: diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 9a1d8f863cc..66e693183ae 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -48,6 +48,7 @@ typedef enum DO_FUNC, DO_AGG, DO_OPERATOR, + DO_ACCESS_METHOD, DO_OPCLASS, DO_OPFAMILY, DO_COLLATION, @@ -167,6 +168,13 @@ typedef struct _oprInfo Oid oprcode; } OprInfo; +typedef struct _accessMethodInfo +{ + DumpableObject dobj; + char amtype; + char *amhandler; +} AccessMethodInfo; + typedef struct _opclassInfo { DumpableObject dobj; @@ -548,6 +556,7 @@ extern TypeInfo *getTypes(Archive *fout, int *numTypes); extern FuncInfo *getFuncs(Archive *fout, int *numFuncs); extern AggInfo *getAggregates(Archive *fout, int *numAggregates); extern OprInfo *getOperators(Archive *fout, int *numOperators); +extern AccessMethodInfo *getAccessMethods(Archive *fout, int *numAccessMethods); extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses); extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies); extern CollInfo *getCollations(Archive *fout, int *numCollations); diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index 78ff59c3429..36de6b62573 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -28,8 +28,8 @@ static const char *modulename = gettext_noop("sorter"); * by OID. (This is a relatively crude hack to provide semi-reasonable * behavior for old databases without full dependency info.) Note: collations, * extensions, text search, foreign-data, materialized view, event trigger, - * policies, transforms, and default ACL objects can't really happen here, so the rather - * bogus priorities for them don't matter. + * policies, transforms, access methods and default ACL objects can't really + * happen here, so the rather bogus priorities for them don't matter. * * NOTE: object-type priorities must match the section assignments made in * pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY, @@ -45,6 +45,7 @@ static const int oldObjectTypePriority[] = 2, /* DO_FUNC */ 3, /* DO_AGG */ 3, /* DO_OPERATOR */ + 3, /* DO_ACCESS_METHOD */ 4, /* DO_OPCLASS */ 4, /* DO_OPFAMILY */ 4, /* DO_COLLATION */ @@ -95,6 +96,7 @@ static const int newObjectTypePriority[] = 6, /* DO_FUNC */ 7, /* DO_AGG */ 8, /* DO_OPERATOR */ + 8, /* DO_ACCESS_METHOD */ 9, /* DO_OPCLASS */ 9, /* DO_OPFAMILY */ 3, /* DO_COLLATION */ @@ -1329,6 +1331,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize) "OPERATOR %s (ID %d OID %u)", obj->name, obj->dumpId, obj->catId.oid); return; + case DO_ACCESS_METHOD: + snprintf(buf, bufsize, + "ACCESS METHOD %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; case DO_OPCLASS: snprintf(buf, bufsize, "OPERATOR CLASS %s (ID %d OID %u)", |