提交 8357ed1d 编写于 作者: D Daniel Gustafsson

Merge upto '693c85d9' from PostgreSQL 8.3

This adds the capability to dump operator families. XML and MSVC build
fixes were already merged and kept at master.

 Conflicts:
	doc/src/sgml/xindex.sgml
	src/backend/executor/execScan.c
	src/backend/utils/adt/xml.c
	src/backend/utils/mb/wchar.c
	src/bin/pg_dump/common.c
	src/bin/pg_dump/pg_backup_archiver.c
	src/bin/pg_dump/pg_dump.c
	src/bin/pg_dump/pg_dump.h
	src/include/port/win32.h
	src/test/regress/expected/xml.out
	src/tools/msvc/Project.pm
	src/tools/msvc/Solution.pm
	src/tools/msvc/mkvcbuild.pl
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.38.2.2 2007/02/02 00:07:27 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.40 2007/01/24 01:25:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......
......@@ -2546,6 +2546,7 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
strcmp(type, "FUNCTION") == 0 ||
strcmp(type, "OPERATOR") == 0 ||
strcmp(type, "OPERATOR CLASS") == 0 ||
strcmp(type, "OPERATOR FAMILY") == 0 ||
strcmp(type, "PROTOCOL") == 0)
{
/* Chop "DROP " off the front and make a modifiable copy */
......@@ -2747,6 +2748,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, "EXTERNAL TABLE") == 0 ||
......
......@@ -206,6 +206,7 @@ static void dumpPlTemplateFunc(Oid funcOid, const char *templateField, PQExpBuff
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);
......@@ -1144,6 +1145,9 @@ dumpMain(bool oids, const char *dumpencoding, int outputBlobs, int plainText, Re
g_gp_supportsPartitioning = g_fout->remoteVersion >= 80209;
g_gp_supportsPartitionTemplates = g_fout->remoteVersion >= 80214;
/* Let cdb_dump_include functions know whether to include opfamilies */
g_gp_supportsOpfamilies = g_fout->remoteVersion >= 80300;
g_gp_supportsAttributeEncoding = testAttributeEncodingSupport();
/*
......@@ -2495,6 +2499,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
if (!postDataSchemaOnly)
dumpOpclass(fout, (OpclassInfo *) dobj);
break;
case DO_OPFAMILY:
dumpOpfamily(fout, (OpfamilyInfo *) dobj);
break;
case DO_CONVERSION:
if (!postDataSchemaOnly)
dumpConversion(fout, (ConvInfo *) dobj);
......@@ -4561,6 +4568,264 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
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
* write out a single conversion definition
......
......@@ -58,6 +58,11 @@ bool g_gp_supportsPartitioning = true;
*/
bool g_gp_supportsPartitionTemplates = true;
/*
* Operator families are only available from 8.3 and onwards.
*/
bool g_gp_supportsOpfamilies = true;
/*
* Indicates whether or not the GPDB cluster supports column attributes.
*/
......@@ -1156,6 +1161,92 @@ getOperators(int *numOprs)
}
/*
* 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
*/
/* Declared in pg_dump.h */
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_gp_supportsOpfamilies == false)
{
*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 (strlen(opfinfo[i].rolname) == 0)
mpp_err_msg(logWarn, progname, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
opfinfo[i].dobj.name);
}
PQclear(res);
destroyPQExpBuffer(query);
return opfinfo;
}
/*
* getConversions:
* read all conversions in the system catalogs and return them in the
......
......@@ -54,6 +54,10 @@ extern bool g_gp_supportsPartitioning;
*/
extern bool g_gp_supportsPartitionTemplates;
/*
* Indicates whether or not the GPDB cluster supports opfamilies.
*/
extern bool g_gp_supportsOpfamilies;
/*
* Indicates whether or not the GPDB cluster supports column attributes.
......
......@@ -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 $
*
*-------------------------------------------------------------------------
*/
......@@ -83,6 +83,7 @@ getSchemaData(int *numTablesPtr)
ProcLangInfo *proclanginfo;
CastInfo *castinfo;
OpclassInfo *opcinfo;
OpfamilyInfo *opfinfo;
ConvInfo *convinfo;
ExtProtInfo *ptcinfo;
int numNamespaces;
......@@ -92,6 +93,7 @@ getSchemaData(int *numTablesPtr)
int numProcLangs;
int numCasts;
int numOpclasses;
int numOpfamilies;
int numConversions;
int numExtProtocols;
const char *LOGGER_INFO = "INFO";
......@@ -139,6 +141,10 @@ getSchemaData(int *numTablesPtr)
status_log_msg(LOGGER_INFO, progname, "reading user-defined operator classes\n");
opcinfo = getOpclasses(&numOpclasses);
if (is_gpdump || g_verbose)
status_log_msg(LOGGER_INFO, progname, "reading user-defined operator families\n");
opfinfo = getOpfamilies(&numOpfamilies);
if(is_gpdump || g_verbose)
status_log_msg(LOGGER_INFO, progname, "reading user-defined conversions\n");
convinfo = getConversions(&numConversions);
......
......@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.138.2.2 2007/08/06 01:38:24 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.139 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2509,6 +2509,7 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
strcmp(type, "FUNCTION") == 0 ||
strcmp(type, "OPERATOR") == 0 ||
strcmp(type, "OPERATOR CLASS") == 0 ||
strcmp(type, "OPERATOR FAMILY") == 0 ||
strcmp(type, "PROTOCOL") == 0)
{
/* Chop "DROP " off the front and make a modifiable copy */
......@@ -2710,6 +2711,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, "EXTERNAL TABLE") == 0 ||
......
......@@ -26,7 +26,7 @@
* http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
*
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -180,6 +180,7 @@ static void dumpPlTemplateFunc(Oid funcOid, const char *templateField, PQExpBuff
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);
......@@ -2453,6 +2454,93 @@ getOpclasses(int *numOpclasses)
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:
* read all the user-defined aggregates in the system catalogs and
......@@ -4486,6 +4574,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
if (!postDataSchemaOnly)
dumpOpclass(fout, (OpclassInfo *) dobj);
break;
case DO_OPFAMILY:
dumpOpfamily(fout, (OpfamilyInfo *) dobj);
break;
case DO_CONVERSION:
if (!postDataSchemaOnly)
dumpConversion(fout, (ConvInfo *) dobj);
......@@ -6555,6 +6646,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;
......@@ -6564,6 +6657,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
char *opcintype;
char *opckeytype;
char *opcdefault;
char *opcfamily;
char *opcfamilynsp;
char *amname;
char *amopstrategy;
char *amopreqcheck;
......@@ -6590,9 +6685,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
......@@ -6600,6 +6699,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",
......@@ -6621,11 +6722,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));
......@@ -6644,9 +6749,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;
......@@ -6673,9 +6788,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);
......@@ -6732,9 +6847,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);
......@@ -6800,6 +6915,264 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
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
* write out a single conversion definition
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, 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.130.2.1 2007/02/19 15:05:21 mha Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.132 2007/01/23 17:54:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -116,6 +116,7 @@ typedef enum
DO_AGG,
DO_OPERATOR,
DO_OPCLASS,
DO_OPFAMILY,
DO_CONVERSION,
DO_TABLE,
DO_ATTRDEF,
......@@ -243,6 +244,12 @@ typedef struct _opclassInfo
char *rolname;
} OpclassInfo;
typedef struct _opfamilyInfo
{
DumpableObject dobj;
char *rolname;
} OpfamilyInfo;
typedef struct _convInfo
{
DumpableObject dobj;
......@@ -482,6 +489,7 @@ extern AggInfo *getAggregates(int *numAggregates);
extern ExtProtInfo *getExtProtocols(int *numExtProtocols);
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);
......
......@@ -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 */
......@@ -63,6 +64,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 */
......@@ -1009,6 +1011,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)",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册