aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump')
-rw-r--r--src/bin/pg_dump/common.c5
-rw-r--r--src/bin/pg_dump/pg_dump.c172
-rw-r--r--src/bin/pg_dump/pg_dump.h9
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c11
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)",