Commit c88540fb authored by Peter Eisentraut's avatar Peter Eisentraut

Dump privileges on functions, aggregates, languages.

parent dd9af92c
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.262 2002/05/18 13:48:00 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.263 2002/05/19 10:08:25 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -99,11 +99,19 @@ static void dumpOneTable(Archive *fout, TableInfo *tbinfo, ...@@ -99,11 +99,19 @@ static void dumpOneTable(Archive *fout, TableInfo *tbinfo,
TableInfo *g_tblinfo); TableInfo *g_tblinfo);
static void dumpOneSequence(Archive *fout, TableInfo *tbinfo, static void dumpOneSequence(Archive *fout, TableInfo *tbinfo,
const bool schemaOnly, const bool dataOnly); const bool schemaOnly, const bool dataOnly);
static void dumpACL(Archive *fout, TableInfo *tbinfo);
static void dumpTableACL(Archive *fout, TableInfo *tbinfo);
static void dumpFuncACL(Archive *fout, FuncInfo *finfo);
static void dumpAggACL(Archive *fout, AggInfo *finfo);
static void dumpACL(Archive *fout, const char *type, const char *name,
const char *nspname, const char *usename,
const char *acl, const char *objoid);
static void dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables); static void dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables);
static void dumpRules(Archive *fout, TableInfo *tblinfo, int numTables); static void dumpRules(Archive *fout, TableInfo *tblinfo, int numTables);
static void formatStringLiteral(PQExpBuffer buf, const char *str, static void formatStringLiteral(PQExpBuffer buf, const char *str,
const formatLiteralOptions opts); const formatLiteralOptions opts);
static char *format_function_signature(FuncInfo *finfo);
static void dumpOneFunc(Archive *fout, FuncInfo *finfo); static void dumpOneFunc(Archive *fout, FuncInfo *finfo);
static void dumpOneOpr(Archive *fout, OprInfo *oprinfo, static void dumpOneOpr(Archive *fout, OprInfo *oprinfo,
OprInfo *g_oprinfo, int numOperators); OprInfo *g_oprinfo, int numOperators);
...@@ -120,7 +128,7 @@ static char *myFormatType(const char *typname, int32 typmod); ...@@ -120,7 +128,7 @@ static char *myFormatType(const char *typname, int32 typmod);
static const char *fmtQualifiedId(const char *schema, const char *id); static const char *fmtQualifiedId(const char *schema, const char *id);
static void AddAcl(char *aclbuf, const char *keyword); static void AddAcl(char *aclbuf, const char *keyword);
static char *GetPrivileges(Archive *AH, const char *s); static char *GetPrivileges(Archive *AH, const char *s, const char *type);
static int dumpBlobs(Archive *AH, char *, void *); static int dumpBlobs(Archive *AH, char *, void *);
static int dumpDatabase(Archive *AH); static int dumpDatabase(Archive *AH);
...@@ -1758,7 +1766,9 @@ getAggregates(int *numAggs) ...@@ -1758,7 +1766,9 @@ getAggregates(int *numAggs)
int i_oid; int i_oid;
int i_aggname; int i_aggname;
int i_aggnamespace; int i_aggnamespace;
int i_aggbasetype;
int i_usename; int i_usename;
int i_aggacl;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema("pg_catalog"); selectSourceSchema("pg_catalog");
...@@ -1769,7 +1779,9 @@ getAggregates(int *numAggs) ...@@ -1769,7 +1779,9 @@ getAggregates(int *numAggs)
{ {
appendPQExpBuffer(query, "SELECT pg_proc.oid, proname as aggname, " appendPQExpBuffer(query, "SELECT pg_proc.oid, proname as aggname, "
"pronamespace as aggnamespace, " "pronamespace as aggnamespace, "
"(select usename from pg_user where proowner = usesysid) as usename " "proargtypes[0]::regtype as aggbasetype, "
"(select usename from pg_user where proowner = usesysid) as usename, "
"proacl as aggacl "
"FROM pg_proc " "FROM pg_proc "
"WHERE proisagg " "WHERE proisagg "
"AND pronamespace != " "AND pronamespace != "
...@@ -1779,7 +1791,10 @@ getAggregates(int *numAggs) ...@@ -1779,7 +1791,10 @@ getAggregates(int *numAggs)
{ {
appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, " appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, "
"0::oid as aggnamespace, " "0::oid as aggnamespace, "
"(select usename from pg_user where aggowner = usesysid) as usename " "CASE WHEN aggbasetype = 0 THEN '-' "
"ELSE format_type(aggbasetype, NULL) END as aggbasetype, "
"(select usename from pg_user where aggowner = usesysid) as usename, "
"cast('{=X}' as aclitem[]) as aggacl "
"from pg_aggregate " "from pg_aggregate "
"where oid > '%u'::oid", "where oid > '%u'::oid",
g_last_builtin_oid); g_last_builtin_oid);
...@@ -1802,7 +1817,9 @@ getAggregates(int *numAggs) ...@@ -1802,7 +1817,9 @@ getAggregates(int *numAggs)
i_oid = PQfnumber(res, "oid"); i_oid = PQfnumber(res, "oid");
i_aggname = PQfnumber(res, "aggname"); i_aggname = PQfnumber(res, "aggname");
i_aggnamespace = PQfnumber(res, "aggnamespace"); i_aggnamespace = PQfnumber(res, "aggnamespace");
i_aggbasetype = PQfnumber(res, "aggbasetype");
i_usename = PQfnumber(res, "usename"); i_usename = PQfnumber(res, "usename");
i_aggacl = PQfnumber(res, "aggacl");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
...@@ -1810,10 +1827,12 @@ getAggregates(int *numAggs) ...@@ -1810,10 +1827,12 @@ getAggregates(int *numAggs)
agginfo[i].aggname = strdup(PQgetvalue(res, i, i_aggname)); agginfo[i].aggname = strdup(PQgetvalue(res, i, i_aggname));
agginfo[i].aggnamespace = findNamespace(PQgetvalue(res, i, i_aggnamespace), agginfo[i].aggnamespace = findNamespace(PQgetvalue(res, i, i_aggnamespace),
agginfo[i].oid); agginfo[i].oid);
agginfo[i].aggbasetype = strdup(PQgetvalue(res, i, i_aggbasetype));
agginfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); agginfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
if (strlen(agginfo[i].usename) == 0) if (strlen(agginfo[i].usename) == 0)
write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n", write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
agginfo[i].aggname); agginfo[i].aggname);
agginfo[i].aggacl = strdup(PQgetvalue(res, i, i_aggacl));
} }
PQclear(res); PQclear(res);
...@@ -1847,6 +1866,7 @@ getFuncs(int *numFuncs) ...@@ -1847,6 +1866,7 @@ getFuncs(int *numFuncs)
int i_pronargs; int i_pronargs;
int i_proargtypes; int i_proargtypes;
int i_prorettype; int i_prorettype;
int i_proacl;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema("pg_catalog"); selectSourceSchema("pg_catalog");
...@@ -1857,7 +1877,7 @@ getFuncs(int *numFuncs) ...@@ -1857,7 +1877,7 @@ getFuncs(int *numFuncs)
{ {
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT pg_proc.oid, proname, prolang, " "SELECT pg_proc.oid, proname, prolang, "
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, proacl, "
"pronamespace, " "pronamespace, "
"(select usename from pg_user where proowner = usesysid) as usename " "(select usename from pg_user where proowner = usesysid) as usename "
"FROM pg_proc " "FROM pg_proc "
...@@ -1870,6 +1890,7 @@ getFuncs(int *numFuncs) ...@@ -1870,6 +1890,7 @@ getFuncs(int *numFuncs)
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT pg_proc.oid, proname, prolang, " "SELECT pg_proc.oid, proname, prolang, "
"pronargs, proargtypes, prorettype, " "pronargs, proargtypes, prorettype, "
"cast('{=X}' as aclitem[]) as proacl, "
"0::oid as pronamespace, " "0::oid as pronamespace, "
"(select usename from pg_user where proowner = usesysid) as usename " "(select usename from pg_user where proowner = usesysid) as usename "
"FROM pg_proc " "FROM pg_proc "
...@@ -1902,6 +1923,7 @@ getFuncs(int *numFuncs) ...@@ -1902,6 +1923,7 @@ getFuncs(int *numFuncs)
i_pronargs = PQfnumber(res, "pronargs"); i_pronargs = PQfnumber(res, "pronargs");
i_proargtypes = PQfnumber(res, "proargtypes"); i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype"); i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
...@@ -1912,6 +1934,7 @@ getFuncs(int *numFuncs) ...@@ -1912,6 +1934,7 @@ getFuncs(int *numFuncs)
finfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang)); finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype)); finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype));
finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (finfo[i].nargs == 0) if (finfo[i].nargs == 0)
finfo[i].argtypes = NULL; finfo[i].argtypes = NULL;
...@@ -3074,7 +3097,7 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs, ...@@ -3074,7 +3097,7 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
* writes out to fout the queries to recreate user-defined procedural languages * writes out to fout the queries to recreate user-defined procedural languages
*/ */
void void
dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs)
{ {
PGresult *res; PGresult *res;
PQExpBuffer query = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer();
...@@ -3086,9 +3109,11 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3086,9 +3109,11 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
int i_lanpltrusted; int i_lanpltrusted;
int i_lanplcallfoid; int i_lanplcallfoid;
int i_lancompiler; int i_lancompiler;
int i_lanacl = -1;
char *lanoid; char *lanoid;
char *lanname; char *lanname;
char *lancompiler; char *lancompiler;
char *lanacl;
const char *lanplcallfoid; const char *lanplcallfoid;
const char *((*deps)[]); const char *((*deps)[]);
int depIdx; int depIdx;
...@@ -3116,6 +3141,8 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3116,6 +3141,8 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
i_lanplcallfoid = PQfnumber(res, "lanplcallfoid"); i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
i_lancompiler = PQfnumber(res, "lancompiler"); i_lancompiler = PQfnumber(res, "lancompiler");
i_oid = PQfnumber(res, "oid"); i_oid = PQfnumber(res, "oid");
if (fout->remoteVersion >= 70300)
i_lanacl = PQfnumber(res, "lanacl");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
...@@ -3123,6 +3150,10 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3123,6 +3150,10 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
lanplcallfoid = PQgetvalue(res, i, i_lanplcallfoid); lanplcallfoid = PQgetvalue(res, i, i_lanplcallfoid);
lanname = PQgetvalue(res, i, i_lanname); lanname = PQgetvalue(res, i, i_lanname);
lancompiler = PQgetvalue(res, i, i_lancompiler); lancompiler = PQgetvalue(res, i, i_lancompiler);
if (fout->remoteVersion >= 70300)
lanacl = PQgetvalue(res, i, i_lanacl);
else
lanacl = "{=U}";
fidx = findFuncByOid(finfo, numFuncs, lanplcallfoid); fidx = findFuncByOid(finfo, numFuncs, lanplcallfoid);
if (fidx < 0) if (fidx < 0)
...@@ -3167,6 +3198,14 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3167,6 +3198,14 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
finfo[fidx].pronamespace->nspname, "", finfo[fidx].pronamespace->nspname, "",
"PROCEDURAL LANGUAGE", deps, "PROCEDURAL LANGUAGE", deps,
defqry->data, delqry->data, NULL, NULL, NULL); defqry->data, delqry->data, NULL, NULL, NULL);
if (!aclsSkip)
{
char * tmp = strdup(fmtId(lanname, force_quotes));
dumpACL(fout, "LANGUAGE", tmp, finfo[fidx].pronamespace->nspname,
NULL, lanacl, lanoid);
free(tmp);
}
} }
PQclear(res); PQclear(res);
...@@ -3181,7 +3220,7 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3181,7 +3220,7 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
* writes out to fout the queries to recreate all the user-defined functions * writes out to fout the queries to recreate all the user-defined functions
*/ */
void void
dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs) dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs)
{ {
int i; int i;
...@@ -3192,9 +3231,47 @@ dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs) ...@@ -3192,9 +3231,47 @@ dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs)
continue; continue;
dumpOneFunc(fout, &finfo[i]); dumpOneFunc(fout, &finfo[i]);
if (!aclsSkip)
dumpFuncACL(fout, &finfo[i]);
}
}
static char *
format_function_signature(FuncInfo *finfo)
{
PQExpBufferData fn;
int j;
initPQExpBuffer(&fn);
appendPQExpBuffer(&fn, "%s (", fmtId(finfo->proname, force_quotes));
for (j = 0; j < finfo->nargs; j++)
{
char *typname;
typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
appendPQExpBuffer(&fn, "%s%s",
(j > 0) ? "," : "",
typname);
free(typname);
} }
appendPQExpBuffer(&fn, ")");
return fn.data;
} }
static void
dumpFuncACL(Archive *fout, FuncInfo *finfo)
{
char *funcsig;
funcsig = format_function_signature(finfo);
dumpACL(fout, "FUNCTION", funcsig, finfo->pronamespace->nspname,
finfo->usename, finfo->proacl, finfo->oid);
free(funcsig);
}
/* /*
* dumpOneFunc: * dumpOneFunc:
* dump out only one function * dump out only one function
...@@ -3204,12 +3281,11 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) ...@@ -3204,12 +3281,11 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
{ {
PQExpBuffer query = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer();
PQExpBuffer q = createPQExpBuffer(); PQExpBuffer q = createPQExpBuffer();
PQExpBuffer fn = createPQExpBuffer();
PQExpBuffer delqry = createPQExpBuffer(); PQExpBuffer delqry = createPQExpBuffer();
PQExpBuffer asPart = createPQExpBuffer(); PQExpBuffer asPart = createPQExpBuffer();
PGresult *res = NULL; PGresult *res = NULL;
char *funcsig = NULL;
int ntups; int ntups;
int j;
char *proretset; char *proretset;
char *prosrc; char *prosrc;
char *probin; char *probin;
...@@ -3316,24 +3392,13 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) ...@@ -3316,24 +3392,13 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
} }
} }
appendPQExpBuffer(fn, "%s (", fmtId(finfo->proname, force_quotes)); funcsig = format_function_signature(finfo);
for (j = 0; j < finfo->nargs; j++)
{
char *typname;
typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
appendPQExpBuffer(fn, "%s%s",
(j > 0) ? "," : "",
typname);
free(typname);
}
appendPQExpBuffer(fn, ")");
appendPQExpBuffer(delqry, "DROP FUNCTION %s;\n", fn->data); appendPQExpBuffer(delqry, "DROP FUNCTION %s;\n", funcsig);
rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque); rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
appendPQExpBuffer(q, "CREATE FUNCTION %s ", fn->data); appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcsig);
appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE %s", appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE %s",
(proretset[0] == 't') ? "SETOF " : "", (proretset[0] == 't') ? "SETOF " : "",
rettypename, rettypename,
...@@ -3367,7 +3432,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) ...@@ -3367,7 +3432,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
appendPQExpBuffer(q, ";\n"); appendPQExpBuffer(q, ";\n");
ArchiveEntry(fout, finfo->oid, fn->data, finfo->pronamespace->nspname, ArchiveEntry(fout, finfo->oid, funcsig, finfo->pronamespace->nspname,
finfo->usename, "FUNCTION", NULL, finfo->usename, "FUNCTION", NULL,
q->data, delqry->data, q->data, delqry->data,
NULL, NULL, NULL); NULL, NULL, NULL);
...@@ -3375,7 +3440,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) ...@@ -3375,7 +3440,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
/*** Dump Function Comments ***/ /*** Dump Function Comments ***/
resetPQExpBuffer(q); resetPQExpBuffer(q);
appendPQExpBuffer(q, "FUNCTION %s", fn->data); appendPQExpBuffer(q, "FUNCTION %s", funcsig);
dumpComment(fout, q->data, dumpComment(fout, q->data,
finfo->pronamespace->nspname, finfo->usename, finfo->pronamespace->nspname, finfo->usename,
finfo->oid, "pg_proc", 0, NULL); finfo->oid, "pg_proc", 0, NULL);
...@@ -3385,9 +3450,9 @@ done: ...@@ -3385,9 +3450,9 @@ done:
destroyPQExpBuffer(query); destroyPQExpBuffer(query);
destroyPQExpBuffer(q); destroyPQExpBuffer(q);
destroyPQExpBuffer(fn);
destroyPQExpBuffer(delqry); destroyPQExpBuffer(delqry);
destroyPQExpBuffer(asPart); destroyPQExpBuffer(asPart);
free(funcsig);
} }
/* /*
...@@ -3744,7 +3809,7 @@ convertOperatorReference(const char *opr, ...@@ -3744,7 +3809,7 @@ convertOperatorReference(const char *opr,
* writes out to fout the queries to create all the user-defined aggregates * writes out to fout the queries to create all the user-defined aggregates
*/ */
void void
dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs) dumpAggs(Archive *fout, AggInfo agginfo[], int numAggs)
{ {
int i; int i;
...@@ -3755,9 +3820,57 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs) ...@@ -3755,9 +3820,57 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs)
continue; continue;
dumpOneAgg(fout, &agginfo[i]); dumpOneAgg(fout, &agginfo[i]);
if (!aclsSkip)
dumpAggACL(fout, &agginfo[i]);
} }
} }
static char *
format_aggregate_signature(AggInfo *agginfo, Archive *fout)
{
PQExpBufferData buf;
bool anybasetype;
initPQExpBuffer(&buf);
appendPQExpBuffer(&buf, "%s",
fmtId(agginfo->aggname, force_quotes));
anybasetype = (strcmp(agginfo->aggbasetype, "-") == 0);
/* If using regtype or format_type, name is already quoted */
if (fout->remoteVersion >= 70100)
{
if (anybasetype)
appendPQExpBuffer(&buf, "(*)");
else
appendPQExpBuffer(&buf, "(%s)", agginfo->aggbasetype);
}
else
{
if (anybasetype)
appendPQExpBuffer(&buf, "(*)");
else
appendPQExpBuffer(&buf, "(%s)",
fmtId(agginfo->aggbasetype, force_quotes));
}
return buf.data;
}
static void
dumpAggACL(Archive *fout, AggInfo *finfo)
{
char *aggsig;
aggsig = format_aggregate_signature(finfo, fout);
dumpACL(fout, "FUNCTION", aggsig, finfo->aggnamespace->nspname,
finfo->usename, finfo->aggacl, finfo->oid);
free(aggsig);
}
/* /*
* dumpOneAgg * dumpOneAgg
* write out a single aggregate definition * write out a single aggregate definition
...@@ -3768,20 +3881,18 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3768,20 +3881,18 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
PQExpBuffer query = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer();
PQExpBuffer q = createPQExpBuffer(); PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer();
PQExpBuffer aggSig = createPQExpBuffer();
PQExpBuffer details = createPQExpBuffer(); PQExpBuffer details = createPQExpBuffer();
char *aggSig;
PGresult *res; PGresult *res;
int ntups; int ntups;
int i_aggtransfn; int i_aggtransfn;
int i_aggfinalfn; int i_aggfinalfn;
int i_aggtranstype; int i_aggtranstype;
int i_aggbasetype;
int i_agginitval; int i_agginitval;
int i_convertok; int i_convertok;
const char *aggtransfn; const char *aggtransfn;
const char *aggfinalfn; const char *aggfinalfn;
const char *aggtranstype; const char *aggtranstype;
const char *aggbasetype;
const char *agginitval; const char *agginitval;
bool convertok; bool convertok;
bool anybasetype; bool anybasetype;
...@@ -3794,7 +3905,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3794,7 +3905,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::regtype, " "aggfinalfn, aggtranstype::regtype, "
"proargtypes[0]::regtype as aggbasetype, "
"agginitval, " "agginitval, "
"'t'::boolean as convertok " "'t'::boolean as convertok "
"from pg_aggregate a, pg_proc p " "from pg_aggregate a, pg_proc p "
...@@ -3806,8 +3916,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3806,8 +3916,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, " appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
"format_type(aggtranstype, NULL) as aggtranstype, " "format_type(aggtranstype, NULL) as aggtranstype, "
"CASE WHEN aggbasetype = 0 THEN '-' "
"ELSE format_type(aggbasetype, NULL) END as aggbasetype, "
"agginitval, 't'::boolean as convertok " "agginitval, 't'::boolean as convertok "
"from pg_aggregate " "from pg_aggregate "
"where oid = '%s'::oid", "where oid = '%s'::oid",
...@@ -3818,8 +3926,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3818,8 +3926,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, "
"aggfinalfn, " "aggfinalfn, "
"(select typname from pg_type where oid = aggtranstype1) as aggtranstype, " "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
"CASE WHEN aggbasetype = 0 THEN '-'::name "
"ELSE (select typname from pg_type where oid = aggbasetype) END as aggbasetype, "
"agginitval1 as agginitval, " "agginitval1 as agginitval, "
"(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok " "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok "
"from pg_aggregate " "from pg_aggregate "
...@@ -3848,47 +3954,25 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3848,47 +3954,25 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
i_aggtransfn = PQfnumber(res, "aggtransfn"); i_aggtransfn = PQfnumber(res, "aggtransfn");
i_aggfinalfn = PQfnumber(res, "aggfinalfn"); i_aggfinalfn = PQfnumber(res, "aggfinalfn");
i_aggtranstype = PQfnumber(res, "aggtranstype"); i_aggtranstype = PQfnumber(res, "aggtranstype");
i_aggbasetype = PQfnumber(res, "aggbasetype");
i_agginitval = PQfnumber(res, "agginitval"); i_agginitval = PQfnumber(res, "agginitval");
i_convertok = PQfnumber(res, "convertok"); i_convertok = PQfnumber(res, "convertok");
aggtransfn = PQgetvalue(res, 0, i_aggtransfn); aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn); aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
aggtranstype = PQgetvalue(res, 0, i_aggtranstype); aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
aggbasetype = PQgetvalue(res, 0, i_aggbasetype);
agginitval = PQgetvalue(res, 0, i_agginitval); agginitval = PQgetvalue(res, 0, i_agginitval);
convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't'); convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
anybasetype = (strcmp(aggbasetype, "-") == 0); aggSig = format_aggregate_signature(agginfo, g_fout);
appendPQExpBuffer(aggSig, "%s",
fmtId(agginfo->aggname, force_quotes));
/* If using regtype or format_type, name is already quoted */
if (g_fout->remoteVersion >= 70100)
{
if (anybasetype)
appendPQExpBuffer(aggSig, "(*)");
else
appendPQExpBuffer(aggSig, "(%s)", aggbasetype);
}
else
{
if (anybasetype)
appendPQExpBuffer(aggSig, "(*)");
else
appendPQExpBuffer(aggSig, "(%s)",
fmtId(aggbasetype, force_quotes));
}
if (!convertok) if (!convertok)
{ {
write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n", write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
aggSig->data); aggSig);
appendPQExpBuffer(q, "-- WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n", appendPQExpBuffer(q, "-- WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
aggSig->data); aggSig);
ArchiveEntry(fout, agginfo->oid, aggSig->data, ArchiveEntry(fout, agginfo->oid, aggSig,
agginfo->aggnamespace->nspname, agginfo->usename, agginfo->aggnamespace->nspname, agginfo->usename,
"WARNING", NULL, "WARNING", NULL,
q->data, "" /* Del */ , q->data, "" /* Del */ ,
...@@ -3896,11 +3980,13 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3896,11 +3980,13 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
return; return;
} }
anybasetype = (strcmp(agginfo->aggbasetype, "-") == 0);
if (g_fout->remoteVersion >= 70300) if (g_fout->remoteVersion >= 70300)
{ {
/* If using 7.3's regproc or regtype, data is already quoted */ /* If using 7.3's regproc or regtype, data is already quoted */
appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s", appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s",
anybasetype ? "'any'" : aggbasetype, anybasetype ? "'any'" : agginfo->aggbasetype,
aggtransfn, aggtransfn,
aggtranstype); aggtranstype);
} }
...@@ -3908,7 +3994,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3908,7 +3994,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
{ {
/* format_type quotes, regproc does not */ /* format_type quotes, regproc does not */
appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s", appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s",
anybasetype ? "'any'" : aggbasetype, anybasetype ? "'any'" : agginfo->aggbasetype,
fmtId(aggtransfn, force_quotes), fmtId(aggtransfn, force_quotes),
aggtranstype); aggtranstype);
} }
...@@ -3917,7 +4003,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3917,7 +4003,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
/* need quotes all around */ /* need quotes all around */
appendPQExpBuffer(details, "BASETYPE = %s, ", appendPQExpBuffer(details, "BASETYPE = %s, ",
anybasetype ? "'any'" : anybasetype ? "'any'" :
fmtId(aggbasetype, force_quotes)); fmtId(agginfo->aggbasetype, force_quotes));
appendPQExpBuffer(details, "SFUNC = %s, ", appendPQExpBuffer(details, "SFUNC = %s, ",
fmtId(aggtransfn, force_quotes)); fmtId(aggtransfn, force_quotes));
appendPQExpBuffer(details, "STYPE = %s", appendPQExpBuffer(details, "STYPE = %s",
...@@ -3936,13 +4022,13 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3936,13 +4022,13 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
aggfinalfn); aggfinalfn);
} }
appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig->data); appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig);
appendPQExpBuffer(q, "CREATE AGGREGATE %s ( %s );\n", appendPQExpBuffer(q, "CREATE AGGREGATE %s ( %s );\n",
fmtId(agginfo->aggname, force_quotes), fmtId(agginfo->aggname, force_quotes),
details->data); details->data);
ArchiveEntry(fout, agginfo->oid, aggSig->data, ArchiveEntry(fout, agginfo->oid, aggSig,
agginfo->aggnamespace->nspname, agginfo->usename, agginfo->aggnamespace->nspname, agginfo->usename,
"AGGREGATE", NULL, "AGGREGATE", NULL,
q->data, delq->data, q->data, delq->data,
...@@ -3951,7 +4037,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3951,7 +4037,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
/*** Dump Aggregate Comments ***/ /*** Dump Aggregate Comments ***/
resetPQExpBuffer(q); resetPQExpBuffer(q);
appendPQExpBuffer(q, "AGGREGATE %s", aggSig->data); appendPQExpBuffer(q, "AGGREGATE %s", aggSig);
if (g_fout->remoteVersion >= 70300) if (g_fout->remoteVersion >= 70300)
dumpComment(fout, q->data, dumpComment(fout, q->data,
agginfo->aggnamespace->nspname, agginfo->usename, agginfo->aggnamespace->nspname, agginfo->usename,
...@@ -3966,8 +4052,8 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) ...@@ -3966,8 +4052,8 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
destroyPQExpBuffer(query); destroyPQExpBuffer(query);
destroyPQExpBuffer(q); destroyPQExpBuffer(q);
destroyPQExpBuffer(delq); destroyPQExpBuffer(delq);
destroyPQExpBuffer(aggSig);
destroyPQExpBuffer(details); destroyPQExpBuffer(details);
free(aggSig);
} }
...@@ -3996,7 +4082,7 @@ AddAcl(char *aclbuf, const char *keyword) ...@@ -3996,7 +4082,7 @@ AddAcl(char *aclbuf, const char *keyword)
* appropriate. * appropriate.
*/ */
static char * static char *
GetPrivileges(Archive *AH, const char *s) GetPrivileges(Archive *AH, const char *s, const char *type)
{ {
char aclbuf[100]; char aclbuf[100];
bool all = true; bool all = true;
...@@ -4009,22 +4095,35 @@ GetPrivileges(Archive *AH, const char *s) ...@@ -4009,22 +4095,35 @@ GetPrivileges(Archive *AH, const char *s)
else \ else \
all = false all = false
CONVERT_PRIV('a', "INSERT"); if (strcmp(type, "TABLE")==0)
CONVERT_PRIV('r', "SELECT"); {
CONVERT_PRIV('R', "RULE"); CONVERT_PRIV('a', "INSERT");
CONVERT_PRIV('r', "SELECT");
CONVERT_PRIV('R', "RULE");
if (AH->remoteVersion >= 70200) if (AH->remoteVersion >= 70200)
{
CONVERT_PRIV('w', "UPDATE");
CONVERT_PRIV('d', "DELETE");
CONVERT_PRIV('x', "REFERENCES");
CONVERT_PRIV('t', "TRIGGER");
}
else
{
/* 7.0 and 7.1 have a simpler worldview */
CONVERT_PRIV('w', "UPDATE,DELETE");
}
}
else if (strcmp(type, "FUNCTION")==0)
{ {
CONVERT_PRIV('w', "UPDATE"); CONVERT_PRIV('X', "EXECUTE");
CONVERT_PRIV('d', "DELETE");
CONVERT_PRIV('x', "REFERENCES");
CONVERT_PRIV('t', "TRIGGER");
} }
else else if (strcmp(type, "LANGUAGE")==0)
{ {
/* 7.0 and 7.1 have a simpler worldview */ CONVERT_PRIV('U', "USAGE");
CONVERT_PRIV('w', "UPDATE,DELETE");
} }
else
abort();
#undef CONVERT_PRIV #undef CONVERT_PRIV
...@@ -4036,18 +4135,25 @@ GetPrivileges(Archive *AH, const char *s) ...@@ -4036,18 +4135,25 @@ GetPrivileges(Archive *AH, const char *s)
/* /*
* dumpACL: * Write out grant/revoke information
* Write out grant/revoke information for a table, view or sequence *
* 'type' must be TABLE, FUNCTION, or LANGUAGE. 'name' is the
* formatted name of the object. Must be quoted etc. already.
* 'nspname' is the namespace the object is in. 'usename' is the
* owner, NULL if there is no owner (for languages). 'acls' is the
* string read out of the fooacl system catalog field; it will be
* parsed here. 'objoid' is the OID of the object for purposes of
* ordering.
*/ */
static void static void
dumpACL(Archive *fout, TableInfo *tbinfo) dumpACL(Archive *fout, const char *type, const char *name,
const char *nspname, const char *usename,
const char *acls, const char *objoid)
{ {
const char *acls = tbinfo->relacl;
char *aclbuf, char *aclbuf,
*tok, *tok,
*eqpos, *eqpos,
*priv; *priv;
char *objoid;
PQExpBuffer sql; PQExpBuffer sql;
bool found_owner_privs = false; bool found_owner_privs = false;
...@@ -4075,8 +4181,8 @@ dumpACL(Archive *fout, TableInfo *tbinfo) ...@@ -4075,8 +4181,8 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
eqpos = strchr(tok, '='); eqpos = strchr(tok, '=');
if (!eqpos) if (!eqpos)
{ {
write_msg(NULL, "could not parse ACL list ('%s') for relation %s\n", write_msg(NULL, "could not parse ACL list ('%s') for %s %s\n",
acls, tbinfo->relname); acls, type, name);
exit_nicely(); exit_nicely();
} }
*eqpos = '\0'; /* it's ok to clobber aclbuf */ *eqpos = '\0'; /* it's ok to clobber aclbuf */
...@@ -4085,10 +4191,11 @@ dumpACL(Archive *fout, TableInfo *tbinfo) ...@@ -4085,10 +4191,11 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
* Parse the privileges (right-hand side). Skip if there are * Parse the privileges (right-hand side). Skip if there are
* none. * none.
*/ */
priv = GetPrivileges(fout, eqpos + 1); priv = GetPrivileges(fout, eqpos + 1, type);
if (*priv) if (*priv)
{ {
if (strcmp(tok, tbinfo->usename) == 0) if (usename && strcmp(tok, usename) == 0)
{ {
/* /*
* For the owner, the default privilege level is ALL. * For the owner, the default privilege level is ALL.
...@@ -4097,12 +4204,11 @@ dumpACL(Archive *fout, TableInfo *tbinfo) ...@@ -4097,12 +4204,11 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
if (strcmp(priv, "ALL") != 0) if (strcmp(priv, "ALL") != 0)
{ {
/* NB: only one fmtId per appendPQExpBuffer! */ /* NB: only one fmtId per appendPQExpBuffer! */
appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ", appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM ",
fmtId(tbinfo->relname, force_quotes)); type, name);
appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes)); appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
appendPQExpBuffer(sql, "GRANT %s ON %s TO ", appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
priv, priv, type, name);
fmtId(tbinfo->relname, force_quotes));
appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes)); appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
} }
} }
...@@ -4111,9 +4217,8 @@ dumpACL(Archive *fout, TableInfo *tbinfo) ...@@ -4111,9 +4217,8 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
/* /*
* Otherwise can assume we are starting from no privs. * Otherwise can assume we are starting from no privs.
*/ */
appendPQExpBuffer(sql, "GRANT %s ON %s TO ", appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
priv, priv, type, name);
fmtId(tbinfo->relname, force_quotes));
if (eqpos == tok) if (eqpos == tok)
{ {
/* Empty left-hand side means "PUBLIC" */ /* Empty left-hand side means "PUBLIC" */
...@@ -4133,34 +4238,39 @@ dumpACL(Archive *fout, TableInfo *tbinfo) ...@@ -4133,34 +4238,39 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
/* /*
* If we didn't find any owner privs, the owner must have revoked 'em all * If we didn't find any owner privs, the owner must have revoked 'em all
*/ */
if (!found_owner_privs && *tbinfo->usename) if (!found_owner_privs && usename)
{ {
appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ", appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM ",
fmtId(tbinfo->relname, force_quotes)); type, name);
appendPQExpBuffer(sql, "%s;\n", fmtId(tbinfo->usename, force_quotes)); appendPQExpBuffer(sql, "%s;\n", fmtId(usename, force_quotes));
} }
free(aclbuf); free(aclbuf);
if (tbinfo->viewoid != NULL) ArchiveEntry(fout, objoid, name, nspname, usename ? usename : "",
objoid = tbinfo->viewoid; "ACL", NULL, sql->data, "", NULL, NULL, NULL);
else
objoid = tbinfo->oid;
ArchiveEntry(fout, objoid, tbinfo->relname,
tbinfo->relnamespace->nspname,
tbinfo->usename, "ACL", NULL,
sql->data, "", NULL, NULL, NULL);
destroyPQExpBuffer(sql); destroyPQExpBuffer(sql);
} }
static void
dumpTableACL(Archive *fout, TableInfo *tbinfo)
{
char * tmp = strdup( fmtId(tbinfo->relname, force_quotes) );
dumpACL(fout, "TABLE", tmp, tbinfo->relnamespace->nspname,
tbinfo->usename, tbinfo->relacl,
tbinfo->viewoid != NULL ? tbinfo->viewoid : tbinfo->oid);
free(tmp);
}
/* /*
* dumpTables: * dumpTables:
* write out to fout the declarations (not data) of all user-defined tables * write out to fout the declarations (not data) of all user-defined tables
*/ */
void void
dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
const bool aclsSkip, const bool schemaOnly, const bool dataOnly) const bool aclsSkip, const bool schemaOnly, const bool dataOnly)
{ {
int i; int i;
...@@ -4176,7 +4286,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, ...@@ -4176,7 +4286,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
{ {
dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly); dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
if (!dataOnly && !aclsSkip) if (!dataOnly && !aclsSkip)
dumpACL(fout, tbinfo); dumpTableACL(fout, tbinfo);
} }
} }
...@@ -4193,7 +4303,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, ...@@ -4193,7 +4303,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
{ {
dumpOneTable(fout, tbinfo, tblinfo); dumpOneTable(fout, tbinfo, tblinfo);
if (!aclsSkip) if (!aclsSkip)
dumpACL(fout, tbinfo); dumpTableACL(fout, tbinfo);
} }
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_dump.h,v 1.85 2002/05/10 22:36:27 tgl Exp $ * $Id: pg_dump.h,v 1.86 2002/05/19 10:08:25 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,6 +62,7 @@ typedef struct _funcInfo ...@@ -62,6 +62,7 @@ typedef struct _funcInfo
int nargs; int nargs;
char **argtypes; /* OIDs */ char **argtypes; /* OIDs */
char *prorettype; /* OID */ char *prorettype; /* OID */
char *proacl;
bool dumped; /* true if already dumped */ bool dumped; /* true if already dumped */
} FuncInfo; } FuncInfo;
...@@ -69,8 +70,10 @@ typedef struct _aggInfo ...@@ -69,8 +70,10 @@ typedef struct _aggInfo
{ {
char *oid; char *oid;
char *aggname; char *aggname;
char *aggbasetype;
NamespaceInfo *aggnamespace; /* link to containing namespace */ NamespaceInfo *aggnamespace; /* link to containing namespace */
char *usename; char *usename;
char *aggacl;
} AggInfo; } AggInfo;
typedef struct _oprInfo typedef struct _oprInfo
...@@ -201,11 +204,11 @@ extern void dumpNamespaces(Archive *fout, ...@@ -201,11 +204,11 @@ extern void dumpNamespaces(Archive *fout,
NamespaceInfo *nsinfo, int numNamespaces); NamespaceInfo *nsinfo, int numNamespaces);
extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs, extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
TypeInfo *tinfo, int numTypes); TypeInfo *tinfo, int numTypes);
extern void dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs); extern void dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs);
extern void dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs); extern void dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs);
extern void dumpAggs(Archive *fout, AggInfo *agginfo, int numAggregates); extern void dumpAggs(Archive *fout, AggInfo agginfo[], int numAggregates);
extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators); extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
extern void dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, extern void dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
const bool aclsSkip, const bool aclsSkip,
const bool schemaOnly, const bool dataOnly); const bool schemaOnly, const bool dataOnly);
extern void dumpIndexes(Archive *fout, TableInfo *tbinfo, int numTables); extern void dumpIndexes(Archive *fout, TableInfo *tbinfo, int numTables);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment