mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Update pg_dump to support dumping operator families.
This commit is contained in:
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
ProcLangInfo *proclanginfo;
|
||||||
CastInfo *castinfo;
|
CastInfo *castinfo;
|
||||||
OpclassInfo *opcinfo;
|
OpclassInfo *opcinfo;
|
||||||
|
OpfamilyInfo *opfinfo;
|
||||||
ConvInfo *convinfo;
|
ConvInfo *convinfo;
|
||||||
int numNamespaces;
|
int numNamespaces;
|
||||||
int numAggregates;
|
int numAggregates;
|
||||||
@ -85,6 +86,7 @@ getSchemaData(int *numTablesPtr)
|
|||||||
int numProcLangs;
|
int numProcLangs;
|
||||||
int numCasts;
|
int numCasts;
|
||||||
int numOpclasses;
|
int numOpclasses;
|
||||||
|
int numOpfamilies;
|
||||||
int numConversions;
|
int numConversions;
|
||||||
|
|
||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
@ -117,6 +119,10 @@ getSchemaData(int *numTablesPtr)
|
|||||||
write_msg(NULL, "reading user-defined operator classes\n");
|
write_msg(NULL, "reading user-defined operator classes\n");
|
||||||
opcinfo = getOpclasses(&numOpclasses);
|
opcinfo = getOpclasses(&numOpclasses);
|
||||||
|
|
||||||
|
if (g_verbose)
|
||||||
|
write_msg(NULL, "reading user-defined operator families\n");
|
||||||
|
opfinfo = getOpfamilies(&numOpfamilies);
|
||||||
|
|
||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
write_msg(NULL, "reading user-defined conversions\n");
|
write_msg(NULL, "reading user-defined conversions\n");
|
||||||
convinfo = getConversions(&numConversions);
|
convinfo = getConversions(&numConversions);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 ||
|
if (strcmp(type, "AGGREGATE") == 0 ||
|
||||||
strcmp(type, "FUNCTION") == 0 ||
|
strcmp(type, "FUNCTION") == 0 ||
|
||||||
strcmp(type, "OPERATOR") == 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 */
|
/* Chop "DROP " off the front and make a modifiable copy */
|
||||||
char *first = strdup(te->dropStmt + 5);
|
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, "FUNCTION") == 0 ||
|
||||||
strcmp(te->desc, "OPERATOR") == 0 ||
|
strcmp(te->desc, "OPERATOR") == 0 ||
|
||||||
strcmp(te->desc, "OPERATOR CLASS") == 0 ||
|
strcmp(te->desc, "OPERATOR CLASS") == 0 ||
|
||||||
|
strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
|
||||||
strcmp(te->desc, "SCHEMA") == 0 ||
|
strcmp(te->desc, "SCHEMA") == 0 ||
|
||||||
strcmp(te->desc, "TABLE") == 0 ||
|
strcmp(te->desc, "TABLE") == 0 ||
|
||||||
strcmp(te->desc, "TYPE") == 0 ||
|
strcmp(te->desc, "TYPE") == 0 ||
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* by PostgreSQL
|
* by PostgreSQL
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 dumpCast(Archive *fout, CastInfo *cast);
|
||||||
static void dumpOpr(Archive *fout, OprInfo *oprinfo);
|
static void dumpOpr(Archive *fout, OprInfo *oprinfo);
|
||||||
static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
|
static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
|
||||||
|
static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
|
||||||
static void dumpConversion(Archive *fout, ConvInfo *convinfo);
|
static void dumpConversion(Archive *fout, ConvInfo *convinfo);
|
||||||
static void dumpRule(Archive *fout, RuleInfo *rinfo);
|
static void dumpRule(Archive *fout, RuleInfo *rinfo);
|
||||||
static void dumpAgg(Archive *fout, AggInfo *agginfo);
|
static void dumpAgg(Archive *fout, AggInfo *agginfo);
|
||||||
@ -2447,6 +2448,93 @@ getOpclasses(int *numOpclasses)
|
|||||||
return opcinfo;
|
return opcinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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:
|
* getAggregates:
|
||||||
* read all the user-defined aggregates in the system catalogs and
|
* read all the user-defined aggregates in the system catalogs and
|
||||||
@ -3771,7 +3859,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
|
|||||||
else if (g_fout->remoteVersion >= 70100)
|
else if (g_fout->remoteVersion >= 70100)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT tgname, tgfoid::regproc as tgfname, "
|
"SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, "
|
||||||
"tgtype, tgnargs, tgargs, tgenabled, "
|
"tgtype, tgnargs, tgargs, tgenabled, "
|
||||||
"tgisconstraint, tgconstrname, tgdeferrable, "
|
"tgisconstraint, tgconstrname, tgdeferrable, "
|
||||||
"tgconstrrelid, tginitdeferred, tableoid, oid, "
|
"tgconstrrelid, tginitdeferred, tableoid, oid, "
|
||||||
@ -3784,7 +3872,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(query,
|
appendPQExpBuffer(query,
|
||||||
"SELECT tgname, tgfoid::regproc as tgfname, "
|
"SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, "
|
||||||
"tgtype, tgnargs, tgargs, tgenabled, "
|
"tgtype, tgnargs, tgargs, tgenabled, "
|
||||||
"tgisconstraint, tgconstrname, tgdeferrable, "
|
"tgisconstraint, tgconstrname, tgdeferrable, "
|
||||||
"tgconstrrelid, tginitdeferred, "
|
"tgconstrrelid, tginitdeferred, "
|
||||||
@ -4864,6 +4952,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
|
|||||||
case DO_OPCLASS:
|
case DO_OPCLASS:
|
||||||
dumpOpclass(fout, (OpclassInfo *) dobj);
|
dumpOpclass(fout, (OpclassInfo *) dobj);
|
||||||
break;
|
break;
|
||||||
|
case DO_OPFAMILY:
|
||||||
|
dumpOpfamily(fout, (OpfamilyInfo *) dobj);
|
||||||
|
break;
|
||||||
case DO_CONVERSION:
|
case DO_CONVERSION:
|
||||||
dumpConversion(fout, (ConvInfo *) dobj);
|
dumpConversion(fout, (ConvInfo *) dobj);
|
||||||
break;
|
break;
|
||||||
@ -6644,6 +6735,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
int i_opcintype;
|
int i_opcintype;
|
||||||
int i_opckeytype;
|
int i_opckeytype;
|
||||||
int i_opcdefault;
|
int i_opcdefault;
|
||||||
|
int i_opcfamily;
|
||||||
|
int i_opcfamilynsp;
|
||||||
int i_amname;
|
int i_amname;
|
||||||
int i_amopstrategy;
|
int i_amopstrategy;
|
||||||
int i_amopreqcheck;
|
int i_amopreqcheck;
|
||||||
@ -6653,6 +6746,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
char *opcintype;
|
char *opcintype;
|
||||||
char *opckeytype;
|
char *opckeytype;
|
||||||
char *opcdefault;
|
char *opcdefault;
|
||||||
|
char *opcfamily;
|
||||||
|
char *opcfamilynsp;
|
||||||
char *amname;
|
char *amname;
|
||||||
char *amopstrategy;
|
char *amopstrategy;
|
||||||
char *amopreqcheck;
|
char *amopreqcheck;
|
||||||
@ -6687,9 +6782,13 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
|
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
|
||||||
"opckeytype::pg_catalog.regtype, "
|
"opckeytype::pg_catalog.regtype, "
|
||||||
"opcdefault, "
|
"opcdefault, "
|
||||||
|
"opfname AS opcfamily, "
|
||||||
|
"nspname AS opcfamilynsp, "
|
||||||
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
|
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
|
||||||
"FROM pg_catalog.pg_opclass "
|
"FROM pg_catalog.pg_opclass c "
|
||||||
"WHERE oid = '%u'::pg_catalog.oid",
|
"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);
|
opcinfo->dobj.catId.oid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -6697,6 +6796,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
|
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
|
||||||
"opckeytype::pg_catalog.regtype, "
|
"opckeytype::pg_catalog.regtype, "
|
||||||
"opcdefault, "
|
"opcdefault, "
|
||||||
|
"NULL AS opcfamily, "
|
||||||
|
"NULL AS opcfamilynsp, "
|
||||||
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
|
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
|
||||||
"FROM pg_catalog.pg_opclass "
|
"FROM pg_catalog.pg_opclass "
|
||||||
"WHERE oid = '%u'::pg_catalog.oid",
|
"WHERE oid = '%u'::pg_catalog.oid",
|
||||||
@ -6718,11 +6819,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
i_opcintype = PQfnumber(res, "opcintype");
|
i_opcintype = PQfnumber(res, "opcintype");
|
||||||
i_opckeytype = PQfnumber(res, "opckeytype");
|
i_opckeytype = PQfnumber(res, "opckeytype");
|
||||||
i_opcdefault = PQfnumber(res, "opcdefault");
|
i_opcdefault = PQfnumber(res, "opcdefault");
|
||||||
|
i_opcfamily = PQfnumber(res, "opcfamily");
|
||||||
|
i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
|
||||||
i_amname = PQfnumber(res, "amname");
|
i_amname = PQfnumber(res, "amname");
|
||||||
|
|
||||||
opcintype = PQgetvalue(res, 0, i_opcintype);
|
opcintype = PQgetvalue(res, 0, i_opcintype);
|
||||||
opckeytype = PQgetvalue(res, 0, i_opckeytype);
|
opckeytype = PQgetvalue(res, 0, i_opckeytype);
|
||||||
opcdefault = PQgetvalue(res, 0, i_opcdefault);
|
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 will still be needed after we PQclear res */
|
||||||
amname = strdup(PQgetvalue(res, 0, i_amname));
|
amname = strdup(PQgetvalue(res, 0, i_amname));
|
||||||
|
|
||||||
@ -6741,9 +6846,19 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
fmtId(opcinfo->dobj.name));
|
fmtId(opcinfo->dobj.name));
|
||||||
if (strcmp(opcdefault, "t") == 0)
|
if (strcmp(opcdefault, "t") == 0)
|
||||||
appendPQExpBuffer(q, "DEFAULT ");
|
appendPQExpBuffer(q, "DEFAULT ");
|
||||||
appendPQExpBuffer(q, "FOR TYPE %s USING %s AS\n ",
|
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
|
||||||
opcintype,
|
opcintype,
|
||||||
fmtId(amname));
|
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;
|
needComma = false;
|
||||||
|
|
||||||
@ -6770,9 +6885,9 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
|
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
|
||||||
"amopopr::pg_catalog.regoperator "
|
"amopopr::pg_catalog.regoperator "
|
||||||
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
|
"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 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 "
|
"AND objid = ao.oid "
|
||||||
"ORDER BY amopstrategy",
|
"ORDER BY amopstrategy",
|
||||||
opcinfo->dobj.catId.oid);
|
opcinfo->dobj.catId.oid);
|
||||||
@ -6829,9 +6944,9 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
appendPQExpBuffer(query, "SELECT amprocnum, "
|
appendPQExpBuffer(query, "SELECT amprocnum, "
|
||||||
"amproc::pg_catalog.regprocedure "
|
"amproc::pg_catalog.regprocedure "
|
||||||
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
|
"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 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 "
|
"AND objid = ap.oid "
|
||||||
"ORDER BY amprocnum",
|
"ORDER BY amprocnum",
|
||||||
opcinfo->dobj.catId.oid);
|
opcinfo->dobj.catId.oid);
|
||||||
@ -6897,6 +7012,264 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
destroyPQExpBuffer(delq);
|
destroyPQExpBuffer(delq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* dumpConversion
|
||||||
* write out a single conversion definition
|
* write out a single conversion definition
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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_AGG,
|
||||||
DO_OPERATOR,
|
DO_OPERATOR,
|
||||||
DO_OPCLASS,
|
DO_OPCLASS,
|
||||||
|
DO_OPFAMILY,
|
||||||
DO_CONVERSION,
|
DO_CONVERSION,
|
||||||
DO_TABLE,
|
DO_TABLE,
|
||||||
DO_ATTRDEF,
|
DO_ATTRDEF,
|
||||||
@ -192,6 +193,12 @@ typedef struct _opclassInfo
|
|||||||
char *rolname;
|
char *rolname;
|
||||||
} OpclassInfo;
|
} OpclassInfo;
|
||||||
|
|
||||||
|
typedef struct _opfamilyInfo
|
||||||
|
{
|
||||||
|
DumpableObject dobj;
|
||||||
|
char *rolname;
|
||||||
|
} OpfamilyInfo;
|
||||||
|
|
||||||
typedef struct _convInfo
|
typedef struct _convInfo
|
||||||
{
|
{
|
||||||
DumpableObject dobj;
|
DumpableObject dobj;
|
||||||
@ -421,6 +428,7 @@ extern FuncInfo *getFuncs(int *numFuncs);
|
|||||||
extern AggInfo *getAggregates(int *numAggregates);
|
extern AggInfo *getAggregates(int *numAggregates);
|
||||||
extern OprInfo *getOperators(int *numOperators);
|
extern OprInfo *getOperators(int *numOperators);
|
||||||
extern OpclassInfo *getOpclasses(int *numOpclasses);
|
extern OpclassInfo *getOpclasses(int *numOpclasses);
|
||||||
|
extern OpfamilyInfo *getOpfamilies(int *numOpfamilies);
|
||||||
extern ConvInfo *getConversions(int *numConversions);
|
extern ConvInfo *getConversions(int *numConversions);
|
||||||
extern TableInfo *getTables(int *numTables);
|
extern TableInfo *getTables(int *numTables);
|
||||||
extern InhInfo *getInherits(int *numInherits);
|
extern InhInfo *getInherits(int *numInherits);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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_AGG */
|
||||||
3, /* DO_OPERATOR */
|
3, /* DO_OPERATOR */
|
||||||
4, /* DO_OPCLASS */
|
4, /* DO_OPCLASS */
|
||||||
|
4, /* DO_OPFAMILY */
|
||||||
5, /* DO_CONVERSION */
|
5, /* DO_CONVERSION */
|
||||||
6, /* DO_TABLE */
|
6, /* DO_TABLE */
|
||||||
8, /* DO_ATTRDEF */
|
8, /* DO_ATTRDEF */
|
||||||
@ -62,6 +63,7 @@ static const int newObjectTypePriority[] =
|
|||||||
5, /* DO_AGG */
|
5, /* DO_AGG */
|
||||||
6, /* DO_OPERATOR */
|
6, /* DO_OPERATOR */
|
||||||
7, /* DO_OPCLASS */
|
7, /* DO_OPCLASS */
|
||||||
|
7, /* DO_OPFAMILY */
|
||||||
9, /* DO_CONVERSION */
|
9, /* DO_CONVERSION */
|
||||||
10, /* DO_TABLE */
|
10, /* DO_TABLE */
|
||||||
12, /* DO_ATTRDEF */
|
12, /* DO_ATTRDEF */
|
||||||
@ -996,6 +998,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
|
|||||||
"OPERATOR CLASS %s (ID %d OID %u)",
|
"OPERATOR CLASS %s (ID %d OID %u)",
|
||||||
obj->name, obj->dumpId, obj->catId.oid);
|
obj->name, obj->dumpId, obj->catId.oid);
|
||||||
return;
|
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:
|
case DO_CONVERSION:
|
||||||
snprintf(buf, bufsize,
|
snprintf(buf, bufsize,
|
||||||
"CONVERSION %s (ID %d OID %u)",
|
"CONVERSION %s (ID %d OID %u)",
|
||||||
|
Reference in New Issue
Block a user