1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

COMMENT ON casts, conversions, languages, operator classes, and

large objects.  Dump all these in pg_dump; also add code to pg_dump
user-defined conversions.  Make psql's large object code rely on
the backend for inserting/deleting LOB comments, instead of trying to
hack pg_description directly.  Documentation and regression tests added.

Christopher Kings-Lynne, code reviewed by Tom
This commit is contained in:
Tom Lane
2003-11-21 22:32:49 +00:00
parent 0a97cb37fc
commit 42ce74bf17
37 changed files with 879 additions and 55 deletions

View File

@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.355 2003/10/28 21:05:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.356 2003/11/21 22:32:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -105,6 +105,7 @@ static const char *convertRegProcReference(const char *proc);
static const char *convertOperatorReference(const char *opr,
OprInfo *g_oprinfo, int numOperators);
static void dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo);
static void dumpOneConversion(Archive *fout, ConvInfo *convinfo);
static void dumpOneAgg(Archive *fout, AggInfo *agginfo);
static Oid findLastBuiltinOid_V71(const char *);
static Oid findLastBuiltinOid_V70(void);
@@ -1689,6 +1690,79 @@ getOperators(int *numOprs)
return oprinfo;
}
/*
* getConversions:
* read all conversions in the system catalogs and return them in the
* ConvInfo* structure
*
* numConversions is set to the number of conversions read in
*/
ConvInfo *
getConversions(int *numConversions)
{
PGresult *res;
int ntups;
int i;
PQExpBuffer query = createPQExpBuffer();
ConvInfo *convinfo;
int i_oid;
int i_conname;
int i_connamespace;
int i_usename;
/* Conversions didn't exist pre-7.3 */
if (g_fout->remoteVersion < 70300) {
*numConversions = 0;
return NULL;
}
/*
* find all conversions, including builtin conversions; we filter out
* system-defined conversions at dump-out time.
*/
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
appendPQExpBuffer(query, "SELECT pg_conversion.oid, conname, "
"connamespace, "
"(select usename from pg_user where conowner = usesysid) as usename "
"from pg_conversion");
res = PQexec(g_conn, query->data);
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{
write_msg(NULL, "query to obtain list of conversions failed: %s", PQerrorMessage(g_conn));
exit_nicely();
}
ntups = PQntuples(res);
*numConversions = ntups;
convinfo = (ConvInfo *) malloc(ntups * sizeof(ConvInfo));
i_oid = PQfnumber(res, "oid");
i_conname = PQfnumber(res, "conname");
i_connamespace = PQfnumber(res, "connamespace");
i_usename = PQfnumber(res, "usename");
for (i = 0; i < ntups; i++)
{
convinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
convinfo[i].conname = strdup(PQgetvalue(res, i, i_conname));
convinfo[i].connamespace = findNamespace(PQgetvalue(res, i, i_connamespace),
convinfo[i].oid);
convinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
}
PQclear(res);
destroyPQExpBuffer(query);
return convinfo;
}
/*
* getOpclasses:
* read all opclasses in the system catalogs and return them in the
@@ -3414,6 +3488,7 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
tinfo->usename, "TYPE", NULL,
q->data, delq->data, NULL, NULL, NULL);
/* Dump Type Comments */
resetPQExpBuffer(q);
@@ -3614,6 +3689,14 @@ dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs)
NULL, lanacl, lanoid);
free(tmp);
}
/* Dump Proc Lang Comments */
resetPQExpBuffer(defqry);
appendPQExpBuffer(defqry, "LANGUAGE %s", fmtId(lanname));
dumpComment(fout, defqry->data,
NULL, "",
lanoid, "pg_language", 0, NULL);
}
PQclear(res);
@@ -4019,6 +4102,16 @@ dumpCasts(Archive *fout,
"CAST", deps,
defqry->data, delqry->data,
NULL, NULL, NULL);
/* Dump Cast Comments */
resetPQExpBuffer(defqry);
appendPQExpBuffer(defqry, "CAST (%s AS %s)",
getFormattedTypeName(castsource, zeroAsNone),
getFormattedTypeName(casttarget, zeroAsNone));
dumpComment(fout, defqry->data,
NULL, "",
castoid, "pg_cast", 0, NULL);
}
PQclear(res);
@@ -4490,7 +4583,8 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
opcintype = PQgetvalue(res, 0, i_opcintype);
opckeytype = PQgetvalue(res, 0, i_opckeytype);
opcdefault = PQgetvalue(res, 0, i_opcdefault);
amname = PQgetvalue(res, 0, i_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
@@ -4617,11 +4711,145 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
q->data, delq->data,
NULL, NULL, NULL);
/* Dump Operator Class Comments */
resetPQExpBuffer(q);
appendPQExpBuffer(q, "OPERATOR CLASS %s",
fmtId(opcinfo->opcname));
appendPQExpBuffer(q, " USING %s",
fmtId(amname));
dumpComment(fout, q->data,
NULL, opcinfo->usename,
opcinfo->oid, "pg_opclass", 0, NULL);
free(amname);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
}
/*
* dumpConversions
* writes out to fout the queries to create all the user-defined conversions
*/
void
dumpConversions(Archive *fout, ConvInfo convinfo[], int numConvs)
{
int i;
for (i = 0; i < numConvs; i++)
{
/* Dump only conversions in dumpable namespaces */
if (!convinfo[i].connamespace->dump)
continue;
dumpOneConversion(fout, &convinfo[i]);
}
}
/*
* dumpOneConversion
* write out a single conversion definition
*/
static void
dumpOneConversion(Archive *fout, ConvInfo *convinfo)
{
PQExpBuffer query = createPQExpBuffer();
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
PQExpBuffer details = createPQExpBuffer();
PGresult *res;
int ntups;
int i_conname;
int i_conforencoding;
int i_contoencoding;
int i_conproc;
int i_condefault;
const char *conname;
const char *conforencoding;
const char *contoencoding;
const char *conproc;
bool condefault;
/* Make sure we are in proper schema */
selectSourceSchema(convinfo->connamespace->nspname);
/* Get conversion-specific details */
appendPQExpBuffer(query, "SELECT conname,
pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding,
pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding,
conproc, condefault
FROM pg_catalog.pg_conversion c
WHERE c.oid = '%s'::pg_catalog.oid",
convinfo->oid);
res = PQexec(g_conn, query->data);
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{
write_msg(NULL, "query to obtain conversion failed: %s",
PQerrorMessage(g_conn));
exit_nicely();
}
/* 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_conname = PQfnumber(res, "conname");
i_conforencoding = PQfnumber(res, "conforencoding");
i_contoencoding = PQfnumber(res, "contoencoding");
i_conproc = PQfnumber(res, "conproc");
i_condefault = PQfnumber(res, "condefault");
conname = PQgetvalue(res, 0, i_conname);
conforencoding = PQgetvalue(res, 0, i_conforencoding);
contoencoding = PQgetvalue(res, 0, i_contoencoding);
conproc = PQgetvalue(res, 0, i_conproc);
condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
/*
* DROP must be fully qualified in case same name appears in
* pg_catalog
*/
appendPQExpBuffer(delq, "DROP CONVERSION %s",
fmtId(convinfo->connamespace->nspname));
appendPQExpBuffer(delq, ".%s;\n",
fmtId(convinfo->conname));
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
(condefault) ? "DEFAULT " : "",
fmtId(convinfo->conname));
appendStringLiteral(q, conforencoding, true);
appendPQExpBuffer(q, " TO ");
appendStringLiteral(q, contoencoding, true);
/* regproc is automatically quoted in 7.3 and above */
appendPQExpBuffer(q, " FROM %s;\n", conproc);
ArchiveEntry(fout, convinfo->oid, convinfo->conname,
convinfo->connamespace->nspname, convinfo->usename,
"CONVERSION", NULL,
q->data, delq->data,
NULL, NULL, NULL);
/* Dump Conversion Comments */
resetPQExpBuffer(q);
appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->conname));
dumpComment(fout, q->data,
convinfo->connamespace->nspname, convinfo->usename,
convinfo->oid, "pg_conversion", 0, NULL);
PQclear(res);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(details);
}
/*
* dumpAggs
@@ -6573,8 +6801,10 @@ dumpRules(Archive *fout, TableInfo *tblinfo, int numTables)
/* Dump rule comments */
resetPQExpBuffer(query);
appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename)));
appendPQExpBuffer(query, " ON %s", fmtId(tbinfo->relname));
appendPQExpBuffer(query, "RULE %s",
fmtId(PQgetvalue(res, i, i_rulename)));
appendPQExpBuffer(query, " ON %s",
fmtId(tbinfo->relname));
dumpComment(fout, query->data,
tbinfo->relnamespace->nspname,
tbinfo->usename,