aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/common.c8
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c6
-rw-r--r--src/bin/pg_dump/pg_dump.c393
-rw-r--r--src/bin/pg_dump/pg_dump.h10
-rw-r--r--src/bin/pg_dump/pg_dump_sort.c9
5 files changed, 411 insertions, 15 deletions
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 409add66c5c..212c952d2c6 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.95 2007/01/05 22:19:48 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.96 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -77,6 +77,7 @@ getSchemaData(int *numTablesPtr)
ProcLangInfo *proclanginfo;
CastInfo *castinfo;
OpclassInfo *opcinfo;
+ OpfamilyInfo *opfinfo;
ConvInfo *convinfo;
int numNamespaces;
int numAggregates;
@@ -85,6 +86,7 @@ getSchemaData(int *numTablesPtr)
int numProcLangs;
int numCasts;
int numOpclasses;
+ int numOpfamilies;
int numConversions;
if (g_verbose)
@@ -118,6 +120,10 @@ getSchemaData(int *numTablesPtr)
opcinfo = getOpclasses(&numOpclasses);
if (g_verbose)
+ write_msg(NULL, "reading user-defined operator families\n");
+ opfinfo = getOpfamilies(&numOpfamilies);
+
+ if (g_verbose)
write_msg(NULL, "reading user-defined conversions\n");
convinfo = getConversions(&numConversions);
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 9b99cb8826f..a4c5d6d7128 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.138 2006/11/21 22:19:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.139 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2443,7 +2443,8 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
if (strcmp(type, "AGGREGATE") == 0 ||
strcmp(type, "FUNCTION") == 0 ||
strcmp(type, "OPERATOR") == 0 ||
- strcmp(type, "OPERATOR CLASS") == 0)
+ strcmp(type, "OPERATOR CLASS") == 0 ||
+ strcmp(type, "OPERATOR FAMILY") == 0)
{
/* Chop "DROP " off the front and make a modifiable copy */
char *first = strdup(te->dropStmt + 5);
@@ -2571,6 +2572,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
strcmp(te->desc, "FUNCTION") == 0 ||
strcmp(te->desc, "OPERATOR") == 0 ||
strcmp(te->desc, "OPERATOR CLASS") == 0 ||
+ strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
strcmp(te->desc, "SCHEMA") == 0 ||
strcmp(te->desc, "TABLE") == 0 ||
strcmp(te->desc, "TYPE") == 0 ||
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 808777eb7cb..c8b3e3916a2 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.457 2007/01/22 01:35:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.458 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -145,6 +145,7 @@ static void dumpFunc(Archive *fout, FuncInfo *finfo);
static void dumpCast(Archive *fout, CastInfo *cast);
static void dumpOpr(Archive *fout, OprInfo *oprinfo);
static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
+static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
static void dumpConversion(Archive *fout, ConvInfo *convinfo);
static void dumpRule(Archive *fout, RuleInfo *rinfo);
static void dumpAgg(Archive *fout, AggInfo *agginfo);
@@ -2448,6 +2449,93 @@ getOpclasses(int *numOpclasses)
}
/*
+ * getOpfamilies:
+ * read all opfamilies in the system catalogs and return them in the
+ * OpfamilyInfo* structure
+ *
+ * numOpfamilies is set to the number of opfamilies read in
+ */
+OpfamilyInfo *
+getOpfamilies(int *numOpfamilies)
+{
+ PGresult *res;
+ int ntups;
+ int i;
+ PQExpBuffer query;
+ OpfamilyInfo *opfinfo;
+ int i_tableoid;
+ int i_oid;
+ int i_opfname;
+ int i_opfnamespace;
+ int i_rolname;
+
+ /* Before 8.3, there is no separate concept of opfamilies */
+ if (g_fout->remoteVersion < 80300)
+ {
+ *numOpfamilies = 0;
+ return NULL;
+ }
+
+ query = createPQExpBuffer();
+
+ /*
+ * find all opfamilies, including builtin opfamilies; we filter out
+ * system-defined opfamilies at dump-out time.
+ */
+
+ /* Make sure we are in proper schema */
+ selectSourceSchema("pg_catalog");
+
+ appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
+ "opfnamespace, "
+ "(%s opfowner) as rolname "
+ "FROM pg_opfamily",
+ username_subquery);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ *numOpfamilies = ntups;
+
+ opfinfo = (OpfamilyInfo *) malloc(ntups * sizeof(OpfamilyInfo));
+
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_opfname = PQfnumber(res, "opfname");
+ i_opfnamespace = PQfnumber(res, "opfnamespace");
+ i_rolname = PQfnumber(res, "rolname");
+
+ for (i = 0; i < ntups; i++)
+ {
+ opfinfo[i].dobj.objType = DO_OPFAMILY;
+ opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+ opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&opfinfo[i].dobj);
+ opfinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opfname));
+ opfinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)),
+ opfinfo[i].dobj.catId.oid);
+ opfinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(opfinfo[i].dobj));
+
+ if (g_fout->remoteVersion >= 70300)
+ {
+ if (strlen(opfinfo[i].rolname) == 0)
+ write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
+ opfinfo[i].dobj.name);
+ }
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+
+ return opfinfo;
+}
+
+/*
* getAggregates:
* read all the user-defined aggregates in the system catalogs and
* return them in the AggInfo* structure
@@ -3771,7 +3859,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
else if (g_fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query,
- "SELECT tgname, tgfoid::regproc as tgfname, "
+ "SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, "
"tgtype, tgnargs, tgargs, tgenabled, "
"tgisconstraint, tgconstrname, tgdeferrable, "
"tgconstrrelid, tginitdeferred, tableoid, oid, "
@@ -3784,7 +3872,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
else
{
appendPQExpBuffer(query,
- "SELECT tgname, tgfoid::regproc as tgfname, "
+ "SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, "
"tgtype, tgnargs, tgargs, tgenabled, "
"tgisconstraint, tgconstrname, tgdeferrable, "
"tgconstrrelid, tginitdeferred, "
@@ -4864,6 +4952,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
case DO_OPCLASS:
dumpOpclass(fout, (OpclassInfo *) dobj);
break;
+ case DO_OPFAMILY:
+ dumpOpfamily(fout, (OpfamilyInfo *) dobj);
+ break;
case DO_CONVERSION:
dumpConversion(fout, (ConvInfo *) dobj);
break;
@@ -6644,6 +6735,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
int i_opcintype;
int i_opckeytype;
int i_opcdefault;
+ int i_opcfamily;
+ int i_opcfamilynsp;
int i_amname;
int i_amopstrategy;
int i_amopreqcheck;
@@ -6653,6 +6746,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
char *opcintype;
char *opckeytype;
char *opcdefault;
+ char *opcfamily;
+ char *opcfamilynsp;
char *amname;
char *amopstrategy;
char *amopreqcheck;
@@ -6687,9 +6782,13 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
"opckeytype::pg_catalog.regtype, "
"opcdefault, "
+ "opfname AS opcfamily, "
+ "nspname AS opcfamilynsp, "
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
- "FROM pg_catalog.pg_opclass "
- "WHERE oid = '%u'::pg_catalog.oid",
+ "FROM pg_catalog.pg_opclass c "
+ "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+ "WHERE c.oid = '%u'::pg_catalog.oid",
opcinfo->dobj.catId.oid);
}
else
@@ -6697,6 +6796,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
"opckeytype::pg_catalog.regtype, "
"opcdefault, "
+ "NULL AS opcfamily, "
+ "NULL AS opcfamilynsp, "
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
"FROM pg_catalog.pg_opclass "
"WHERE oid = '%u'::pg_catalog.oid",
@@ -6718,11 +6819,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
i_opcintype = PQfnumber(res, "opcintype");
i_opckeytype = PQfnumber(res, "opckeytype");
i_opcdefault = PQfnumber(res, "opcdefault");
+ i_opcfamily = PQfnumber(res, "opcfamily");
+ i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
i_amname = PQfnumber(res, "amname");
opcintype = PQgetvalue(res, 0, i_opcintype);
opckeytype = PQgetvalue(res, 0, i_opckeytype);
opcdefault = PQgetvalue(res, 0, i_opcdefault);
+ opcfamily = PQgetvalue(res, 0, i_opcfamily);
+ opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
/* amname will still be needed after we PQclear res */
amname = strdup(PQgetvalue(res, 0, i_amname));
@@ -6741,9 +6846,19 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
fmtId(opcinfo->dobj.name));
if (strcmp(opcdefault, "t") == 0)
appendPQExpBuffer(q, "DEFAULT ");
- appendPQExpBuffer(q, "FOR TYPE %s USING %s AS\n ",
+ appendPQExpBuffer(q, "FOR TYPE %s USING %s",
opcintype,
fmtId(amname));
+ if (strlen(opcfamily) > 0 &&
+ (strcmp(opcfamily, opcinfo->dobj.name) != 0 ||
+ strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
+ {
+ appendPQExpBuffer(q, " FAMILY ");
+ if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
+ appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
+ appendPQExpBuffer(q, "%s", fmtId(opcfamily));
+ }
+ appendPQExpBuffer(q, " AS\n ");
needComma = false;
@@ -6770,9 +6885,9 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
"amopopr::pg_catalog.regoperator "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opclass'::regclass "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amop'::regclass "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
"AND objid = ao.oid "
"ORDER BY amopstrategy",
opcinfo->dobj.catId.oid);
@@ -6829,9 +6944,9 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
appendPQExpBuffer(query, "SELECT amprocnum, "
"amproc::pg_catalog.regprocedure "
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opclass'::regclass "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amproc'::regclass "
+ "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
"AND objid = ap.oid "
"ORDER BY amprocnum",
opcinfo->dobj.catId.oid);
@@ -6898,6 +7013,264 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
}
/*
+ * dumpOpfamily
+ * write out a single operator family definition
+ */
+static void
+dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
+{
+ PQExpBuffer query;
+ PQExpBuffer q;
+ PQExpBuffer delq;
+ PGresult *res;
+ PGresult *res_ops;
+ PGresult *res_procs;
+ int ntups;
+ int i_amname;
+ int i_amopstrategy;
+ int i_amopreqcheck;
+ int i_amopopr;
+ int i_amprocnum;
+ int i_amproc;
+ int i_amproclefttype;
+ int i_amprocrighttype;
+ char *amname;
+ char *amopstrategy;
+ char *amopreqcheck;
+ char *amopopr;
+ char *amprocnum;
+ char *amproc;
+ char *amproclefttype;
+ char *amprocrighttype;
+ bool needComma;
+ int i;
+
+ /* Skip if not to be dumped */
+ if (!opfinfo->dobj.dump || dataOnly)
+ return;
+
+ /*
+ * We want to dump the opfamily only if (1) it contains "loose" operators
+ * or functions, or (2) it contains an opclass with a different name or
+ * owner. Otherwise it's sufficient to let it be created during creation
+ * of the contained opclass, and not dumping it improves portability of
+ * the dump. Since we have to fetch the loose operators/funcs anyway,
+ * do that first.
+ */
+
+ query = createPQExpBuffer();
+ q = createPQExpBuffer();
+ delq = createPQExpBuffer();
+
+ /* Make sure we are in proper schema so regoperator works correctly */
+ selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
+
+ /*
+ * Fetch only those opfamily members that are tied directly to the opfamily
+ * by pg_depend entries.
+ */
+ appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+ "amopopr::pg_catalog.regoperator "
+ "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+ "AND objid = ao.oid "
+ "ORDER BY amopstrategy",
+ opfinfo->dobj.catId.oid);
+
+ res_ops = PQexec(g_conn, query->data);
+ check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
+
+ resetPQExpBuffer(query);
+
+ appendPQExpBuffer(query, "SELECT amprocnum, "
+ "amproc::pg_catalog.regprocedure, "
+ "amproclefttype::pg_catalog.regtype, "
+ "amprocrighttype::pg_catalog.regtype "
+ "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+ "AND objid = ap.oid "
+ "ORDER BY amprocnum",
+ opfinfo->dobj.catId.oid);
+
+ res_procs = PQexec(g_conn, query->data);
+ check_sql_result(res_procs, g_conn, query->data, PGRES_TUPLES_OK);
+
+ if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
+ {
+ /* No loose members, so check contained opclasses */
+ resetPQExpBuffer(query);
+
+ appendPQExpBuffer(query, "SELECT 1 "
+ "FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
+ "WHERE f.oid = '%u'::pg_catalog.oid "
+ "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refobjid = f.oid "
+ "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "AND objid = c.oid "
+ "AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
+ "LIMIT 1",
+ opfinfo->dobj.catId.oid);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ if (PQntuples(res) == 0)
+ {
+ /* no need to dump it, so bail out */
+ PQclear(res);
+ PQclear(res_ops);
+ PQclear(res_procs);
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+ return;
+ }
+
+ PQclear(res);
+ }
+
+ /* Get additional fields from the pg_opfamily row */
+ resetPQExpBuffer(query);
+
+ appendPQExpBuffer(query, "SELECT "
+ "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
+ "FROM pg_catalog.pg_opfamily "
+ "WHERE oid = '%u'::pg_catalog.oid",
+ opfinfo->dobj.catId.oid);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ /* Expecting a single result only */
+ ntups = PQntuples(res);
+ if (ntups != 1)
+ {
+ write_msg(NULL, "Got %d rows instead of one from: %s",
+ ntups, query->data);
+ exit_nicely();
+ }
+
+ i_amname = PQfnumber(res, "amname");
+
+ /* amname will still be needed after we PQclear res */
+ amname = strdup(PQgetvalue(res, 0, i_amname));
+
+ /*
+ * DROP must be fully qualified in case same name appears in pg_catalog
+ */
+ appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
+ fmtId(opfinfo->dobj.namespace->dobj.name));
+ appendPQExpBuffer(delq, ".%s",
+ fmtId(opfinfo->dobj.name));
+ appendPQExpBuffer(delq, " USING %s;\n",
+ fmtId(amname));
+
+ /* Build the fixed portion of the CREATE command */
+ appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
+ fmtId(opfinfo->dobj.name));
+ appendPQExpBuffer(q, " USING %s;\n",
+ fmtId(amname));
+
+ PQclear(res);
+
+ /* Do we need an ALTER to add loose members? */
+ if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
+ {
+ appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
+ fmtId(opfinfo->dobj.name));
+ appendPQExpBuffer(q, " USING %s ADD\n ",
+ fmtId(amname));
+
+ needComma = false;
+
+ /*
+ * Now fetch and print the OPERATOR entries (pg_amop rows).
+ */
+ ntups = PQntuples(res_ops);
+
+ i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
+ i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck");
+ i_amopopr = PQfnumber(res_ops, "amopopr");
+
+ for (i = 0; i < ntups; i++)
+ {
+ amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
+ amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck);
+ amopopr = PQgetvalue(res_ops, i, i_amopopr);
+
+ if (needComma)
+ appendPQExpBuffer(q, " ,\n ");
+
+ appendPQExpBuffer(q, "OPERATOR %s %s",
+ amopstrategy, amopopr);
+ if (strcmp(amopreqcheck, "t") == 0)
+ appendPQExpBuffer(q, " RECHECK");
+
+ needComma = true;
+ }
+
+ /*
+ * Now fetch and print the FUNCTION entries (pg_amproc rows).
+ */
+ ntups = PQntuples(res_procs);
+
+ i_amprocnum = PQfnumber(res_procs, "amprocnum");
+ i_amproc = PQfnumber(res_procs, "amproc");
+ i_amproclefttype = PQfnumber(res_procs, "amproclefttype");
+ i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype");
+
+ for (i = 0; i < ntups; i++)
+ {
+ amprocnum = PQgetvalue(res_procs, i, i_amprocnum);
+ amproc = PQgetvalue(res_procs, i, i_amproc);
+ amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype);
+ amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
+
+ if (needComma)
+ appendPQExpBuffer(q, " ,\n ");
+
+ appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
+ amprocnum, amproclefttype, amprocrighttype,
+ amproc);
+
+ needComma = true;
+ }
+
+ appendPQExpBuffer(q, ";\n");
+ }
+
+ ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
+ opfinfo->dobj.name,
+ opfinfo->dobj.namespace->dobj.name,
+ NULL,
+ opfinfo->rolname,
+ false, "OPERATOR FAMILY", q->data, delq->data, NULL,
+ opfinfo->dobj.dependencies, opfinfo->dobj.nDeps,
+ NULL, NULL);
+
+ /* Dump Operator Family Comments */
+ resetPQExpBuffer(q);
+ appendPQExpBuffer(q, "OPERATOR FAMILY %s",
+ fmtId(opfinfo->dobj.name));
+ appendPQExpBuffer(q, " USING %s",
+ fmtId(amname));
+ dumpComment(fout, q->data,
+ NULL, opfinfo->rolname,
+ opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
+
+ free(amname);
+ PQclear(res_ops);
+ PQclear(res_procs);
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+}
+
+/*
* dumpConversion
* write out a single conversion definition
*/
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 0949ae2731f..9ba74aa98ee 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.131 2007/01/05 22:19:48 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.132 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -96,6 +96,7 @@ typedef enum
DO_AGG,
DO_OPERATOR,
DO_OPCLASS,
+ DO_OPFAMILY,
DO_CONVERSION,
DO_TABLE,
DO_ATTRDEF,
@@ -192,6 +193,12 @@ typedef struct _opclassInfo
char *rolname;
} OpclassInfo;
+typedef struct _opfamilyInfo
+{
+ DumpableObject dobj;
+ char *rolname;
+} OpfamilyInfo;
+
typedef struct _convInfo
{
DumpableObject dobj;
@@ -421,6 +428,7 @@ extern FuncInfo *getFuncs(int *numFuncs);
extern AggInfo *getAggregates(int *numAggregates);
extern OprInfo *getOperators(int *numOperators);
extern OpclassInfo *getOpclasses(int *numOpclasses);
+extern OpfamilyInfo *getOpfamilies(int *numOpfamilies);
extern ConvInfo *getConversions(int *numConversions);
extern TableInfo *getTables(int *numTables);
extern InhInfo *getInherits(int *numInherits);
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 5425bda2300..2d51ace1923 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.16 2007/01/05 22:19:48 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.17 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,6 +33,7 @@ static const int oldObjectTypePriority[] =
3, /* DO_AGG */
3, /* DO_OPERATOR */
4, /* DO_OPCLASS */
+ 4, /* DO_OPFAMILY */
5, /* DO_CONVERSION */
6, /* DO_TABLE */
8, /* DO_ATTRDEF */
@@ -62,6 +63,7 @@ static const int newObjectTypePriority[] =
5, /* DO_AGG */
6, /* DO_OPERATOR */
7, /* DO_OPCLASS */
+ 7, /* DO_OPFAMILY */
9, /* DO_CONVERSION */
10, /* DO_TABLE */
12, /* DO_ATTRDEF */
@@ -996,6 +998,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
"OPERATOR CLASS %s (ID %d OID %u)",
obj->name, obj->dumpId, obj->catId.oid);
return;
+ case DO_OPFAMILY:
+ snprintf(buf, bufsize,
+ "OPERATOR FAMILY %s (ID %d OID %u)",
+ obj->name, obj->dumpId, obj->catId.oid);
+ return;
case DO_CONVERSION:
snprintf(buf, bufsize,
"CONVERSION %s (ID %d OID %u)",