1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

First pass at schema-fying pg_dump/pg_restore. Much to do still,

but the basic capability seems to work.
This commit is contained in:
Tom Lane
2002-05-10 22:36:27 +00:00
parent 1011fb651d
commit 9f0ae0c820
13 changed files with 4137 additions and 3801 deletions

View File

@ -3,30 +3,15 @@
* common.c
* common routines between pg_dump and pg4_dump
*
* Since pg4_dump is long-dead code, there is no longer any useful distinction
* between this file and pg_dump.c.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.63 2002/04/24 02:44:19 momjian Exp $
*
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
*
* - Fixed dumpTable output to output lengths for char and varchar types!
* - Added single. quote to twin single quote expansion for 'insert' string
* mode.
*
* Modifications 14-Sep-2000 - pjw@rhyme.com.au
* - Added enum for findTypeByOid to specify how to handle OID and which
* string to return - formatted type, or base type. If the base type
* is returned then fmtId is called on the string.
*
* Modifications 4-Apr-2001 - pjw@rhyme.com.au
* - Changed flagInhAttrs to check all parent tables for overridden settings
* and set flags accordingly.
*
* BEWARE: Since fmtId uses a static buffer, using 'useBaseTypeName' on more
* than one call in a line will cause problems.
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.64 2002/05/10 22:36:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -44,64 +29,368 @@
#include "strdup.h"
#endif
static char **findParentsByOid(TableInfo *tbinfo, int numTables,
InhInfo *inhinfo, int numInherits,
const char *oid,
int *numParents,
int (**parentIndexes)[]);
static int findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
static void findParentsByOid(TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits,
const char *oid,
int *numParentsPtr, int **parentIndexes);
static void flagInhTables(TableInfo *tbinfo, int numTables,
InhInfo *inhinfo, int numInherits);
static void flagInhAttrs(TableInfo *tbinfo, int numTables,
InhInfo *inhinfo, int numInherits);
static int strInArray(const char *pattern, char **arr, int arr_size);
/*
* findTypeByOid
* given an oid of a type, return its typename
* dumpSchema:
* we have a valid connection, we are now going to dump the schema
* into the file
*/
TableInfo *
dumpSchema(Archive *fout,
int *numTablesPtr,
const bool aclsSkip,
const bool schemaOnly,
const bool dataOnly)
{
int numNamespaces;
int numTypes;
int numFuncs;
int numTables;
int numInherits;
int numAggregates;
int numOperators;
NamespaceInfo *nsinfo;
TypeInfo *tinfo;
FuncInfo *finfo;
AggInfo *agginfo;
TableInfo *tblinfo;
InhInfo *inhinfo;
OprInfo *oprinfo;
if (g_verbose)
write_msg(NULL, "reading namespaces\n");
nsinfo = getNamespaces(&numNamespaces);
if (g_verbose)
write_msg(NULL, "reading user-defined types\n");
tinfo = getTypes(&numTypes);
if (g_verbose)
write_msg(NULL, "reading user-defined functions\n");
finfo = getFuncs(&numFuncs);
if (g_verbose)
write_msg(NULL, "reading user-defined aggregate functions\n");
agginfo = getAggregates(&numAggregates);
if (g_verbose)
write_msg(NULL, "reading user-defined operators\n");
oprinfo = getOperators(&numOperators);
if (g_verbose)
write_msg(NULL, "reading user-defined tables\n");
tblinfo = getTables(&numTables);
if (g_verbose)
write_msg(NULL, "reading table inheritance information\n");
inhinfo = getInherits(&numInherits);
/* Link tables to parents, mark parents of target tables interesting */
if (g_verbose)
write_msg(NULL, "finding inheritance relationships\n");
flagInhTables(tblinfo, numTables, inhinfo, numInherits);
if (g_verbose)
write_msg(NULL, "reading column info for interesting tables\n");
getTableAttrs(tblinfo, numTables);
if (g_verbose)
write_msg(NULL, "flagging inherited columns in subtables\n");
flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out database comment\n");
dumpDBComment(fout);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined namespaces\n");
dumpNamespaces(fout, nsinfo, numNamespaces);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined types\n");
dumpTypes(fout, finfo, numFuncs, tinfo, numTypes);
}
if (g_verbose)
write_msg(NULL, "dumping out tables\n");
dumpTables(fout, tblinfo, numTables,
aclsSkip, schemaOnly, dataOnly);
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out indexes\n");
dumpIndexes(fout, tblinfo, numTables);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined procedural languages\n");
dumpProcLangs(fout, finfo, numFuncs);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined functions\n");
dumpFuncs(fout, finfo, numFuncs);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined aggregate functions\n");
dumpAggs(fout, agginfo, numAggregates);
}
if (!dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined operators\n");
dumpOprs(fout, oprinfo, numOperators);
}
*numTablesPtr = numTables;
return tblinfo;
}
/* flagInhTables -
* Fill in parentIndexes fields of every target table, and mark
* parents of target tables as interesting
*
* Can return various special cases for oid 0.
* Note that only direct ancestors of targets are marked interesting.
* This is sufficient; we don't much care whether they inherited their
* attributes or not.
*
* modifies tblinfo
*/
static void
flagInhTables(TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits)
{
int i,
j;
int numParents;
int *parentIndexes;
for (i = 0; i < numTables; i++)
{
/* Sequences and views never have parents */
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
tblinfo[i].relkind == RELKIND_VIEW)
continue;
/* Don't bother computing anything for non-target tables, either */
if (!tblinfo[i].dump)
continue;
/* Find all the immediate parent tables */
findParentsByOid(tblinfo, numTables,
inhinfo, numInherits,
tblinfo[i].oid,
&tblinfo[i].numParents,
&tblinfo[i].parentIndexes);
numParents = tblinfo[i].numParents;
parentIndexes = tblinfo[i].parentIndexes;
/* Mark the parents as interesting for getTableAttrs */
for (j = 0; j < numParents; j++)
{
int parentInd = parentIndexes[j];
tblinfo[parentInd].interesting = true;
}
}
}
/* flagInhAttrs -
* for each dumpable table in tblinfo, flag its inherited attributes
* so when we dump the table out, we don't dump out the inherited attributes
*
* modifies tblinfo
*/
static void
flagInhAttrs(TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits)
{
int i,
j,
k;
int parentInd;
int inhAttrInd;
int numParents;
int *parentIndexes;
bool foundAttr; /* Attr was found in a parent */
bool foundNotNull; /* Attr was NOT NULL in a parent */
bool defaultsMatch; /* All non-empty defaults match */
bool defaultsFound; /* Found a default in a parent */
char *attrDef;
char *inhDef;
for (i = 0; i < numTables; i++)
{
/* Sequences and views never have parents */
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
tblinfo[i].relkind == RELKIND_VIEW)
continue;
/* Don't bother computing anything for non-target tables, either */
if (!tblinfo[i].dump)
continue;
numParents = tblinfo[i].numParents;
parentIndexes = tblinfo[i].parentIndexes;
if (numParents == 0)
continue; /* nothing to see here, move along */
/*
* For each attr, check the parent info: if no parent has an attr
* with the same name, then it's not inherited. If there *is* an
* attr with the same name, then only dump it if:
*
* - it is NOT NULL and zero parents are NOT NULL OR - it has a
* default value AND the default value does not match all parent
* default values, or no parents specify a default.
*
* See discussion on -hackers around 2-Apr-2001.
*/
for (j = 0; j < tblinfo[i].numatts; j++)
{
foundAttr = false;
foundNotNull = false;
defaultsMatch = true;
defaultsFound = false;
attrDef = tblinfo[i].adef_expr[j];
for (k = 0; k < numParents; k++)
{
parentInd = parentIndexes[k];
inhAttrInd = strInArray(tblinfo[i].attnames[j],
tblinfo[parentInd].attnames,
tblinfo[parentInd].numatts);
if (inhAttrInd != -1)
{
foundAttr = true;
foundNotNull |= tblinfo[parentInd].notnull[inhAttrInd];
if (attrDef != NULL) /* If we have a default,
* check parent */
{
inhDef = tblinfo[parentInd].adef_expr[inhAttrInd];
if (inhDef != NULL)
{
defaultsFound = true;
defaultsMatch &= (strcmp(attrDef, inhDef) == 0);
}
}
}
}
/*
* Based on the scan of the parents, decide if we can rely on
* the inherited attr
*/
if (foundAttr) /* Attr was inherited */
{
/* Set inherited flag by default */
tblinfo[i].inhAttrs[j] = true;
tblinfo[i].inhAttrDef[j] = true;
tblinfo[i].inhNotNull[j] = true;
/*
* Clear it if attr had a default, but parents did not, or
* mismatch
*/
if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
{
tblinfo[i].inhAttrs[j] = false;
tblinfo[i].inhAttrDef[j] = false;
}
/*
* Clear it if NOT NULL and none of the parents were NOT
* NULL
*/
if (tblinfo[i].notnull[j] && !foundNotNull)
{
tblinfo[i].inhAttrs[j] = false;
tblinfo[i].inhNotNull[j] = false;
}
}
}
}
}
/*
* findTableByOid
* finds the index (in tblinfo) of the table with the given oid
* returns -1 if not found
*
* NOTE: should hash this, but just do linear search for now
*/
char *
findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts)
int
findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
{
int i;
if (strcmp(oid, "0") == 0)
for (i = 0; i < numTables; i++)
{
if ((opts & zeroAsOpaque) != 0)
return g_opaque_type;
else if ((opts & zeroAsAny) != 0)
return "'any'";
else if ((opts & zeroAsStar) != 0)
return "*";
else if ((opts & zeroAsNone) != 0)
return "NONE";
if (strcmp(tblinfo[i].oid, oid) == 0)
return i;
}
return -1;
}
for (i = 0; i < numTypes; i++)
/*
* findFuncByOid
* finds the index (in finfo) of the function with the given OID
* returns -1 if not found
*
* NOTE: should hash this, but just do linear search for now
*/
int
findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid)
{
int i;
for (i = 0; i < numFuncs; i++)
{
if (strcmp(tinfo[i].oid, oid) == 0)
{
if ((opts & useBaseTypeName) != 0)
return (char *) fmtId(tinfo[i].typname, false);
else
return tinfo[i].typedefn;
}
if (strcmp(finfo[i].oid, oid) == 0)
return i;
}
/* no suitable type name was found */
return (NULL);
return -1;
}
/*
* findOprByOid
* given the oid of an operator, return the name of the operator
*
*
* NOTE: should hash this, but just do linear search for now
*
*/
char *
findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
@ -124,23 +413,22 @@ findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
/*
* findParentsByOid
* given the oid of a class, return the names of its parent classes
* and assign the number of parents, and parent indexes to the last arguments.
* given the oid of a class, find its parent classes in tblinfo[]
*
*
* returns NULL if none
* Returns the number of parents and their array indexes into the
* last two arguments.
*/
static char **
static void
findParentsByOid(TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits, const char *oid,
int *numParentsPtr, int (**parentIndexes)[])
InhInfo *inhinfo, int numInherits,
const char *oid,
int *numParentsPtr, int **parentIndexes)
{
int i,
j;
int parentInd,
selfInd;
char **result;
int numParents;
numParents = 0;
@ -154,8 +442,7 @@ findParentsByOid(TableInfo *tblinfo, int numTables,
if (numParents > 0)
{
result = (char **) malloc(sizeof(char *) * numParents);
(*parentIndexes) = malloc(sizeof(int) * numParents);
*parentIndexes = (int *) malloc(sizeof(int) * numParents);
j = 0;
for (i = 0; i < numInherits; i++)
{
@ -178,17 +465,12 @@ findParentsByOid(TableInfo *tblinfo, int numTables,
exit_nicely();
}
(**parentIndexes)[j] = parentInd;
result[j++] = tblinfo[parentInd].relname;
(*parentIndexes)[j++] = parentInd;
}
}
return result;
}
else
{
(*parentIndexes) = NULL;
return NULL;
}
*parentIndexes = NULL;
}
/*
@ -247,7 +529,6 @@ parseNumericArray(const char *str, char **array, int arraysize)
* takes in a string and a string array and the number of elements in the
* string array.
* returns the index if the string is somewhere in the array, -1 otherwise
*
*/
static int
@ -262,333 +543,3 @@ strInArray(const char *pattern, char **arr, int arr_size)
}
return -1;
}
/*
* dumpSchema:
* we have a valid connection, we are now going to dump the schema
* into the file
*
*/
TableInfo *
dumpSchema(Archive *fout,
int *numTablesPtr,
const char *tablename,
const bool aclsSkip,
const bool oids,
const bool schemaOnly,
const bool dataOnly)
{
int numTypes;
int numFuncs;
int numTables;
int numInherits;
int numAggregates;
int numOperators;
int numIndexes;
TypeInfo *tinfo = NULL;
FuncInfo *finfo = NULL;
AggInfo *agginfo = NULL;
TableInfo *tblinfo = NULL;
InhInfo *inhinfo = NULL;
OprInfo *oprinfo = NULL;
IndInfo *indinfo = NULL;
if (g_verbose)
write_msg(NULL, "reading user-defined types\n");
tinfo = getTypes(&numTypes);
if (g_verbose)
write_msg(NULL, "reading user-defined functions\n");
finfo = getFuncs(&numFuncs);
if (g_verbose)
write_msg(NULL, "reading user-defined aggregate functions\n");
agginfo = getAggregates(&numAggregates);
if (g_verbose)
write_msg(NULL, "reading user-defined operators\n");
oprinfo = getOperators(&numOperators);
if (g_verbose)
write_msg(NULL, "reading user-defined tables\n");
tblinfo = getTables(&numTables, finfo, numFuncs, tablename);
if (g_verbose)
write_msg(NULL, "reading index information\n");
indinfo = getIndexes(&numIndexes);
if (g_verbose)
write_msg(NULL, "reading table inheritance information\n");
inhinfo = getInherits(&numInherits);
if (g_verbose)
write_msg(NULL, "finding the column names and types for each table\n");
getTableAttrs(tblinfo, numTables);
if (g_verbose)
write_msg(NULL, "flagging inherited columns in subtables\n");
flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
if (!tablename && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out database comment\n");
dumpDBComment(fout);
}
if (!tablename && fout)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined types\n");
dumpTypes(fout, finfo, numFuncs, tinfo, numTypes);
}
if (g_verbose)
write_msg(NULL, "dumping out tables\n");
dumpTables(fout, tblinfo, numTables, tablename,
aclsSkip, schemaOnly, dataOnly);
if (fout && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out indexes\n");
dumpIndexes(fout, indinfo, numIndexes, tblinfo, numTables, tablename);
}
if (!tablename && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined procedural languages\n");
dumpProcLangs(fout, finfo, numFuncs, tinfo, numTypes);
}
if (!tablename && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined functions\n");
dumpFuncs(fout, finfo, numFuncs, tinfo, numTypes);
}
if (!tablename && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined aggregate functions\n");
dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes);
}
if (!tablename && !dataOnly)
{
if (g_verbose)
write_msg(NULL, "dumping out user-defined operators\n");
dumpOprs(fout, oprinfo, numOperators, tinfo, numTypes);
}
*numTablesPtr = numTables;
clearAggInfo(agginfo, numAggregates);
clearOprInfo(oprinfo, numOperators);
clearTypeInfo(tinfo, numTypes);
clearFuncInfo(finfo, numFuncs);
clearInhInfo(inhinfo, numInherits);
clearIndInfo(indinfo, numIndexes);
return tblinfo;
}
/* flagInhAttrs -
* for each table in tblinfo, flag its inherited attributes
* so when we dump the table out, we don't dump out the inherited attributes
*
* initializes the parentRels field of each table
*
* modifies tblinfo
*
*/
static void
flagInhAttrs(TableInfo *tblinfo, int numTables,
InhInfo *inhinfo, int numInherits)
{
int i,
j,
k;
int parentInd;
int inhAttrInd;
int (*parentIndexes)[];
bool foundAttr; /* Attr was found in a parent */
bool foundNotNull; /* Attr was NOT NULL in a parent */
bool defaultsMatch; /* All non-empty defaults match */
bool defaultsFound; /* Found a default in a parent */
char *attrDef;
char *inhDef;
/*
* we go backwards because the tables in tblinfo are in OID order,
* meaning the subtables are after the parent tables we flag inherited
* attributes from child tables first
*/
for (i = numTables - 1; i >= 0; i--)
{
/* Sequences can never have parents, and attr info is undefined */
if (tblinfo[i].relkind == RELKIND_SEQUENCE)
continue;
/* Get all the parents and their indexes. */
tblinfo[i].parentRels = findParentsByOid(tblinfo, numTables,
inhinfo, numInherits,
tblinfo[i].oid,
&tblinfo[i].numParents,
&parentIndexes);
/*
* For each attr, check the parent info: if no parent has an attr
* with the same name, then it's not inherited. If there *is* an
* attr with the same name, then only dump it if:
*
* - it is NOT NULL and zero parents are NOT NULL OR - it has a
* default value AND the default value does not match all parent
* default values, or no parents specify a default.
*
* See discussion on -hackers around 2-Apr-2001.
*/
for (j = 0; j < tblinfo[i].numatts; j++)
{
foundAttr = false;
foundNotNull = false;
defaultsMatch = true;
defaultsFound = false;
attrDef = tblinfo[i].adef_expr[j];
for (k = 0; k < tblinfo[i].numParents; k++)
{
parentInd = (*parentIndexes)[k];
if (parentInd < 0)
{
/* shouldn't happen unless findParentsByOid is broken */
write_msg(NULL, "failed sanity check, table \"%s\" not found by flagInhAttrs\n",
tblinfo[i].parentRels[k]);
exit_nicely();
};
inhAttrInd = strInArray(tblinfo[i].attnames[j],
tblinfo[parentInd].attnames,
tblinfo[parentInd].numatts);
if (inhAttrInd != -1)
{
foundAttr = true;
foundNotNull |= tblinfo[parentInd].notnull[inhAttrInd];
if (attrDef != NULL) /* It we have a default,
* check parent */
{
inhDef = tblinfo[parentInd].adef_expr[inhAttrInd];
if (inhDef != NULL)
{
defaultsFound = true;
defaultsMatch &= (strcmp(attrDef, inhDef) == 0);
};
};
};
};
/*
* Based on the scan of the parents, decide if we can rely on
* the inherited attr
*/
if (foundAttr) /* Attr was inherited */
{
/* Set inherited flag by default */
tblinfo[i].inhAttrs[j] = 1;
tblinfo[i].inhAttrDef[j] = 1;
tblinfo[i].inhNotNull[j] = 1;
/*
* Clear it if attr had a default, but parents did not, or
* mismatch
*/
if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
{
tblinfo[i].inhAttrs[j] = 0;
tblinfo[i].inhAttrDef[j] = 0;
}
/*
* Clear it if NOT NULL and none of the parents were NOT
* NULL
*/
if (tblinfo[i].notnull[j] && !foundNotNull)
{
tblinfo[i].inhAttrs[j] = 0;
tblinfo[i].inhNotNull[j] = 0;
}
}
}
}
}
/*
* findTableByName
* finds the index (in tblinfo) of the table with the given relname
* returns -1 if not found
*
* NOTE: should hash this, but just do linear search for now
*/
int
findTableByName(TableInfo *tblinfo, int numTables, const char *relname)
{
int i;
for (i = 0; i < numTables; i++)
{
if (strcmp(tblinfo[i].relname, relname) == 0)
return i;
}
return -1;
}
/*
* findTableByOid
* finds the index (in tblinfo) of the table with the given oid
* returns -1 if not found
*
* NOTE: should hash this, but just do linear search for now
*/
static int
findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
{
int i;
for (i = 0; i < numTables; i++)
{
if (strcmp(tblinfo[i].oid, oid) == 0)
return i;
}
return -1;
}
/*
* findFuncByName
* finds the index (in finfo) of the function with the given name
* returns -1 if not found
*
* NOTE: should hash this, but just do linear search for now
*/
int
findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
{
int i;
for (i = 0; i < numFuncs; i++)
{
if (strcmp(finfo[i].proname, name) == 0)
return i;
}
return -1;
}

View File

@ -15,27 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.18 2002/02/11 00:18:20 tgl Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
*
* Initial version.
*
*
* Modifications - 28-Jul-2000 - pjw@rhyme.com.au (1.45)
*
* Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
* Added code to dump 'Create Schema' statement (pg_dump)
* Don't bother to disable/enable triggers if we don't have a superuser (pg_restore)
* Cleaned up code for reconnecting to database.
* Force a reconnect as superuser before enabling/disabling triggers.
*
* Modifications - 31-Jul-2000 - pjw@rhyme.com.au (1.46, 1.47)
* Added & Removed --throttle (pg_dump)
* Fixed minor bug in language dumping code: expbuffres were not being reset.
* Fixed version number initialization in _allocAH (pg_backup_archiver.c)
* Added second connection when restoring BLOBs to allow temp. table to survive
* (db reconnection causes temp tables to be lost).
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.19 2002/05/10 22:36:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -87,6 +67,7 @@ typedef struct _restoreOptions
* cirsumstances */
int use_setsessauth;/* use SET SESSSION AUTHORIZATION instead
* of \connect */
int disable_triggers;/* disable triggers during data-only restore */
char *superuser; /* Username to use as superuser */
int dataOnly;
int dropSchema;
@ -152,10 +133,12 @@ PGconn *ConnectDatabase(Archive *AH,
/* Called to add a TOC entry */
extern void ArchiveEntry(Archive *AH, const char *oid, const char *name,
const char *desc, const char *((*deps)[]), const char *defn,
const char *dropStmt, const char *copyStmt, const char *owner,
DataDumperPtr dumpFn, void *dumpArg);
extern void ArchiveEntry(Archive *AHX, const char *oid, const char *name,
const char *namespace, const char *owner,
const char *desc, const char *((*deps)[]),
const char *defn, const char *dropStmt,
const char *copyStmt,
DataDumperPtr dumpFn, void *dumpArg);
/* Called to write *data* to the archive */
extern int WriteData(Archive *AH, const void *data, int dLen);

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.45 2002/05/06 17:34:45 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.46 2002/05/10 22:36:26 tgl Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
*
@ -95,8 +95,10 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
const int compression, ArchiveMode mode);
static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData);
static void _doSetSessionAuth(ArchiveHandle *AH, const char *autharg);
static void _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te);
static void _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user);
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt);
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
@ -208,23 +210,13 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
AHX->minRemoteVersion = 070100;
AHX->maxRemoteVersion = 999999;
ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, ropt->username,
ConnectDatabase(AHX, ropt->dbname,
ropt->pghost, ropt->pgport, ropt->username,
ropt->requirePassword, ropt->ignoreVersion);
/*
* If no superuser was specified then see if the current user will
* do...
*/
if (!ropt->superuser)
{
if (UserIsSuperuser(AH, ConnectedUser(AH)))
ropt->superuser = strdup(ConnectedUser(AH));
}
}
/*
* Work out if we have an implied data-only retore. This can happen if
* Work out if we have an implied data-only restore. This can happen if
* the dump was data only or if the user has used a toc list to
* exclude all of the schema data. All we do is look for schema
* entries - if none are found then we set the dataOnly flag.
@ -253,12 +245,6 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
}
}
if (!ropt->superuser)
write_msg(modulename, "WARNING:\n"
" Data restoration may fail because existing triggers cannot be disabled\n"
" (no superuser user name specified). This is only a problem when\n"
" restoring into a database with already existing triggers.\n");
/*
* Setup the output file if necessary.
*/
@ -280,8 +266,9 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
{
/* We want the schema */
ahlog(AH, 1, "dropping %s %s\n", te->desc, te->name);
/* Reconnect if necessary */
/* Select owner and schema as necessary */
_reconnectAsOwner(AH, NULL, te);
_selectOutputSchema(AH, te->namespace);
/* Drop it */
ahprintf(AH, "%s", te->dropStmt);
}
@ -376,6 +363,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
* have reconnected)
*/
_reconnectAsOwner(AH, NULL, te);
_selectOutputSchema(AH, te->namespace);
ahlog(AH, 1, "restoring data for table %s\n", te->name);
@ -433,7 +421,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
if ((reqs & REQ_DATA) != 0) /* We loaded the data */
{
ahlog(AH, 1, "fixing up large object cross-reference for %s\n", te->name);
FixupBlobRefs(AH, te->name);
FixupBlobRefs(AH, te);
}
}
else
@ -501,30 +489,31 @@ _canRestoreBlobs(ArchiveHandle *AH)
static void
_disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
{
char *oldUser = NULL;
char *oldUser;
char *oldSchema;
/* Can't do much if we're connected & don't have a superuser */
/* Also, don't bother with triggers unless a data-only retore. */
if (!ropt->dataOnly || (_restoringToDB(AH) && !ropt->superuser))
/* This hack is only needed in a data-only restore */
if (!ropt->dataOnly || !ropt->disable_triggers)
return;
oldUser = strdup(AH->currUser);
oldSchema = strdup(AH->currSchema);
/*
* Reconnect as superuser if possible, since they are the only ones
* who can update pg_class...
* Become superuser if possible, since they are the only ones
* who can update pg_class. If -S was not given, but we are allowed
* to use SET SESSION AUTHORIZATION, assume the initial user identity
* is a superuser. Otherwise we just have to bull ahead anyway.
*/
if (ropt->superuser)
{
if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH))
{
/*
* If we're not allowing changes for ownership, then remember
* the user so we can change it back here. Otherwise, let
* _reconnectAsOwner do what it has to do.
*/
if (ropt->noOwner)
oldUser = strdup(ConnectedUser(AH));
_reconnectAsUser(AH, NULL, ropt->superuser);
}
_reconnectAsUser(AH, NULL, ropt->superuser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
{
_doSetSessionAuth(AH, "DEFAULT");
}
ahlog(AH, 1, "disabling triggers\n");
@ -538,52 +527,59 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop
/*
* Just update the AFFECTED table, if known.
*/
if (te && te->name && strlen(te->name) > 0)
ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" = '%s';\n\n",
te->name);
ahprintf(AH, "UPDATE pg_class SET reltriggers = 0 "
"WHERE oid = '%s'::regclass;\n\n",
fmtId(te->name, false));
else
ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" !~ '^pg_';\n\n");
ahprintf(AH, "UPDATE pg_class SET reltriggers = 0 FROM pg_namespace "
"WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
/*
* Restore the user connection from the start of this procedure if
* _reconnectAsOwner is disabled.
* Restore original user and schema state.
*/
if (ropt->noOwner && oldUser)
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, oldUser);
free(oldUser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
{
_doSetSessionAuth(AH, fmtId(oldUser, false));
}
free(oldUser);
free(oldSchema);
}
static void
_enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
{
char *oldUser = NULL;
char *oldUser;
char *oldSchema;
/* Can't do much if we're connected & don't have a superuser */
/* Also, don't bother with triggers unless a data-only retore. */
if (!ropt->dataOnly || (_restoringToDB(AH) && !ropt->superuser))
/* This hack is only needed in a data-only restore */
if (!ropt->dataOnly || !ropt->disable_triggers)
return;
oldUser = strdup(AH->currUser);
oldSchema = strdup(AH->currSchema);
/*
* Reconnect as superuser if possible, since they are the only ones
* who can update pg_class...
* Become superuser if possible, since they are the only ones
* who can update pg_class. If -S was not given, but we are allowed
* to use SET SESSION AUTHORIZATION, assume the initial user identity
* is a superuser. Otherwise we just have to bull ahead anyway.
*/
if (ropt->superuser)
{
if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH))
{
/*
* If we're not allowing changes for ownership, then remember
* the user so we can change it back here. Otherwise, let
* _reconnectAsOwner do what it has to do
*/
if (ropt->noOwner)
oldUser = strdup(ConnectedUser(AH));
_reconnectAsUser(AH, NULL, ropt->superuser);
}
_reconnectAsUser(AH, NULL, ropt->superuser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
{
_doSetSessionAuth(AH, "DEFAULT");
}
ahlog(AH, 1, "enabling triggers\n");
@ -593,29 +589,36 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt
* 'SET' command when one is available.
*/
ahprintf(AH, "-- Enable triggers\n");
if (te && te->name && strlen(te->name) > 0)
{
ahprintf(AH, "UPDATE pg_class SET reltriggers = "
"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
"WHERE relname = '%s';\n\n",
te->name);
}
else
{
ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = "
"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
"WHERE \"relname\" !~ '^pg_';\n\n");
}
/*
* Restore the user connection from the start of this procedure if
* _reconnectAsOwner is disabled.
* Just update the AFFECTED table, if known.
*/
if (ropt->noOwner && oldUser)
if (te && te->name && strlen(te->name) > 0)
ahprintf(AH, "UPDATE pg_class SET reltriggers = "
"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
"WHERE oid = '%s'::regclass;\n\n",
fmtId(te->name, false));
else
ahprintf(AH, "UPDATE pg_class SET reltriggers = "
"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
"FROM pg_namespace "
"WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
/*
* Restore original user and schema state.
*/
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, oldUser);
free(oldUser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
{
_doSetSessionAuth(AH, fmtId(oldUser, false));
}
free(oldUser);
free(oldSchema);
}
/*
@ -642,8 +645,10 @@ WriteData(Archive *AHX, const void *data, int dLen)
/* Public */
void
ArchiveEntry(Archive *AHX, const char *oid, const char *name,
const char *desc, const char *((*deps)[]), const char *defn,
const char *dropStmt, const char *copyStmt, const char *owner,
const char *namespace, const char *owner,
const char *desc, const char *((*deps)[]),
const char *defn, const char *dropStmt,
const char *copyStmt,
DataDumperPtr dumpFn, void *dumpArg)
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
@ -664,21 +669,21 @@ ArchiveEntry(Archive *AHX, const char *oid, const char *name,
newToc->id = AH->lastID;
newToc->name = strdup(name);
newToc->namespace = namespace ? strdup(namespace) : NULL;
newToc->owner = strdup(owner);
newToc->desc = strdup(desc);
newToc->oid = strdup(oid);
newToc->depOid = deps;
_fixupOidInfo(newToc);
newToc->defn = strdup(defn);
newToc->dropStmt = strdup(dropStmt);
newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
newToc->owner = strdup(owner);
newToc->oid = strdup(oid);
newToc->depOid = deps; /* NB: not copied */
_fixupOidInfo(newToc);
newToc->printed = 0;
newToc->formatData = NULL;
newToc->dataDumper = dumpFn,
newToc->dataDumperArg = dumpArg;
newToc->dataDumper = dumpFn;
newToc->dataDumperArg = dumpArg;
newToc->hadDumper = dumpFn ? 1 : 0;
@ -1667,6 +1672,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
AH->currUser = strdup(""); /* So it's valid, but we can free() it
* later if necessary */
AH->currSchema = strdup(""); /* ditto */
AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
if (!AH->toc)
@ -1789,6 +1795,7 @@ WriteToc(ArchiveHandle *AH)
WriteStr(AH, te->defn);
WriteStr(AH, te->dropStmt);
WriteStr(AH, te->copyStmt);
WriteStr(AH, te->namespace);
WriteStr(AH, te->owner);
/* Dump list of dependencies */
@ -1840,6 +1847,9 @@ ReadToc(ArchiveHandle *AH)
if (AH->version >= K_VERS_1_3)
te->copyStmt = ReadStr(AH);
if (AH->version >= K_VERS_1_6)
te->namespace = ReadStr(AH);
te->owner = ReadStr(AH);
/* Read TOC entry dependencies */
@ -1975,6 +1985,33 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
return res;
}
/*
* Issue a SET SESSION AUTHORIZATION command. Caller is responsible
* for updating state if appropriate. Note that caller must also quote
* the argument if it's a username (it might be DEFAULT, too).
*/
static void
_doSetSessionAuth(ArchiveHandle *AH, const char *autharg)
{
if (RestoringToDB(AH))
{
PQExpBuffer qry = createPQExpBuffer();
PGresult *res;
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;", autharg);
res = PQexec(AH->connection, qry->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
die_horribly(AH, modulename, "could not set session user to %s: %s",
autharg, PQerrorMessage(AH->connection));
PQclear(res);
destroyPQExpBuffer(qry);
}
else
ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n", autharg);
}
/*
* Issue the commands to connect to the database as the specified user
@ -1999,25 +2036,7 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
*/
if (!dbname && AH->ropt->use_setsessauth)
{
if (RestoringToDB(AH))
{
PQExpBuffer qry = createPQExpBuffer();
PGresult *res;
appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;",
fmtId(user, false));
res = PQexec(AH->connection, qry->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
die_horribly(AH, modulename, "could not set session user to %s: %s",
user, PQerrorMessage(AH->connection));
PQclear(res);
destroyPQExpBuffer(qry);
}
else
ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n",
fmtId(user, false));
_doSetSessionAuth(AH, fmtId(user, false));
}
else if (AH->ropt && AH->ropt->noReconnect)
{
@ -2038,6 +2057,11 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
ahprintf(AH, qry->data);
destroyPQExpBuffer(qry);
/* don't assume we still know the output schema */
if (AH->currSchema)
free(AH->currSchema);
AH->currSchema = strdup("");
}
/*
@ -2066,6 +2090,43 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
}
/*
* Issue the commands to select the specified schema as the current schema
* in the target database.
*/
static void
_selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
{
if (!schemaName || *schemaName == '\0' ||
strcmp(AH->currSchema, schemaName) == 0)
return; /* no need to do anything */
if (RestoringToDB(AH))
{
PQExpBuffer qry = createPQExpBuffer();
PGresult *res;
appendPQExpBuffer(qry, "SET search_path = %s;",
fmtId(schemaName, false));
res = PQexec(AH->connection, qry->data);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
die_horribly(AH, modulename, "could not set search_path to %s: %s",
schemaName, PQerrorMessage(AH->connection));
PQclear(res);
destroyPQExpBuffer(qry);
}
else
ahprintf(AH, "SET search_path = %s;\n\n",
fmtId(schemaName, false));
if (AH->currSchema)
free(AH->currSchema);
AH->currSchema = strdup(schemaName);
}
/*
* fmtId
*
@ -2139,16 +2200,19 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
{
char *pfx;
/* Reconnect if necessary */
/* Select owner and schema as necessary */
_reconnectAsOwner(AH, NULL, te);
_selectOutputSchema(AH, te->namespace);
if (isData)
pfx = "Data for ";
else
pfx = "";
ahprintf(AH, "--\n-- %sTOC Entry ID %d (OID %s)\n--\n-- Name: %s Type: %s Owner: %s\n",
pfx, te->id, te->oid, te->name, te->desc, te->owner);
ahprintf(AH, "--\n-- %sTOC Entry ID %d (OID %s)\n--\n-- Name: %s Type: %s Schema: %s Owner: %s\n",
pfx, te->id, te->oid, te->name, te->desc,
te->namespace ? te->namespace : "-",
te->owner);
if (AH->PrintExtraTocPtr !=NULL)
(*AH->PrintExtraTocPtr) (AH, te);
ahprintf(AH, "--\n\n");

View File

@ -17,17 +17,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.42 2002/04/24 02:21:04 momjian Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
* - Initial version.
*
* Modifications - 15-Sep-2000 - pjw@rhyme.com.au
* - Added braceDepth to sqlparseInfo to handle braces in rule definitions.
*
* Modifications - 31-Mar-2001 - pjw@rhyme.com.au (1.50)
* - Make dependencies work on ArchiveEntry calls so that UDTs will
* dump in correct order.
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.43 2002/05/10 22:36:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -68,8 +58,8 @@ typedef z_stream *z_streamp;
#include "libpq-fe.h"
#define K_VERS_MAJOR 1
#define K_VERS_MINOR 5
#define K_VERS_REV 7
#define K_VERS_MINOR 6
#define K_VERS_REV 0
/* Data block types */
#define BLK_DATA 1
@ -82,7 +72,8 @@ typedef z_stream *z_streamp;
#define K_VERS_1_3 (( (1 * 256 + 3) * 256 + 0) * 256 + 0) /* BLOBs */
#define K_VERS_1_4 (( (1 * 256 + 4) * 256 + 0) * 256 + 0) /* Date & name in header */
#define K_VERS_1_5 (( (1 * 256 + 5) * 256 + 0) * 256 + 0) /* Handle dependencies */
#define K_VERS_MAX (( (1 * 256 + 5) * 256 + 255) * 256 + 0)
#define K_VERS_1_6 (( (1 * 256 + 6) * 256 + 0) * 256 + 0) /* Schema field in TOCs */
#define K_VERS_MAX (( (1 * 256 + 6) * 256 + 255) * 256 + 0)
/* No of BLOBs to restore in 1 TX */
#define BLOB_BATCH_SIZE 100
@ -235,6 +226,7 @@ typedef struct _archiveHandle
int tocCount; /* Number of TOC entries */
struct _tocEntry *currToc; /* Used when dumping data */
char *currUser; /* Restore: current username in script */
char *currSchema; /* Restore: current schema in script */
int compression; /* Compression requested on open */
ArchiveMode mode; /* File mode - r or w */
void *formatData; /* Header data specific to file format */
@ -254,11 +246,12 @@ typedef struct _tocEntry
int hadDumper; /* Archiver was passed a dumper routine
* (used in restore) */
char *name;
char *namespace; /* null or empty string if not in a schema */
char *owner;
char *desc;
char *defn;
char *dropStmt;
char *copyStmt;
char *owner;
char *oid; /* Oid of source of entry */
Oid oidVal; /* Value of above */
const char *((*depOid)[]);
@ -314,9 +307,6 @@ extern OutputContext SetOutput(ArchiveHandle *AH, char *filename, int compressio
extern void ResetOutput(ArchiveHandle *AH, OutputContext savedContext);
extern int RestoringToDB(ArchiveHandle *AH);
extern int ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser);
extern int UserIsSuperuser(ArchiveHandle *AH, char *user);
extern char *ConnectedUser(ArchiveHandle *AH);
extern int ConnectedUserIsSuperuser(ArchiveHandle *AH);
int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH);
int ahprintf(ArchiveHandle *AH, const char *fmt,...) __attribute__((format(printf, 2, 3)));

View File

@ -5,25 +5,7 @@
* Implements the basic DB functions used by the archiver.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.31 2002/01/18 19:17:05 momjian Exp $
*
* NOTES
*
* Modifications - 04-Jan-2001 - pjw@rhyme.com.au
*
* - Check results of PQ routines more carefully.
*
* Modifications - 19-Mar-2001 - pjw@rhyme.com.au
*
* - Avoid forcing table name to lower case in FixupBlobXrefs!
*
*
* Modifications - 18-Jan-2002 - pjw@rhyme.com.au
*
* - Split ExecuteSqlCommandBuf into 3 routines for (slightly) improved
* clarity. Modify loop to cater for COPY commands buried in the SQL
* command buffer (prev version assumed COPY command was executed
* in prior call). This was to fix the buf in the 'set max oid' code.
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.32 2002/05/10 22:36:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -219,57 +201,6 @@ _check_database_version(ArchiveHandle *AH, bool ignoreVersion)
}
}
/*
* Check if a given user is a superuser.
*/
int
UserIsSuperuser(ArchiveHandle *AH, char *user)
{
PQExpBuffer qry = createPQExpBuffer();
PGresult *res;
int i_usesuper;
int ntups;
int isSuper;
/* Get the superuser setting */
appendPQExpBuffer(qry, "select usesuper from pg_user where usename = '%s'", user);
res = PQexec(AH->connection, qry->data);
if (!res)
die_horribly(AH, modulename, "null result checking superuser status of %s\n", user);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
die_horribly(AH, modulename, "could not check superuser status of %s: %s",
user, PQerrorMessage(AH->connection));
ntups = PQntuples(res);
if (ntups == 0)
isSuper = 0;
else
{
i_usesuper = PQfnumber(res, "usesuper");
isSuper = (strcmp(PQgetvalue(res, 0, i_usesuper), "t") == 0);
}
PQclear(res);
destroyPQExpBuffer(qry);
return isSuper;
}
int
ConnectedUserIsSuperuser(ArchiveHandle *AH)
{
return UserIsSuperuser(AH, PQuser(AH->connection));
}
char *
ConnectedUser(ArchiveHandle *AH)
{
return PQuser(AH->connection);
}
/*
* Reconnect to the server. If dbname is not NULL, use that database,
* else the one associated with the archive handle. If username is
@ -310,6 +241,11 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username)
AH->username = strdup(newusername);
/* XXX Why don't we update AH->dbname? */
/* don't assume we still know the output schema */
if (AH->currSchema)
free(AH->currSchema);
AH->currSchema = strdup("");
return 1;
}
@ -481,13 +417,6 @@ ConnectDatabase(Archive *AHX,
PQsetNoticeProcessor(AH->connection, notice_processor, NULL);
/*
* AH->currUser = PQuser(AH->connection);
*
* Removed because it prevented an initial \connect when dumping to SQL
* in pg_dump.
*/
return AH->connection;
}
@ -775,8 +704,9 @@ ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qryv, int bufLen)
}
void
FixupBlobRefs(ArchiveHandle *AH, char *tablename)
FixupBlobRefs(ArchiveHandle *AH, TocEntry *te)
{
PQExpBuffer tblName;
PQExpBuffer tblQry;
PGresult *res,
*uRes;
@ -784,44 +714,55 @@ FixupBlobRefs(ArchiveHandle *AH, char *tablename)
n;
char *attr;
if (strcmp(tablename, BLOB_XREF_TABLE) == 0)
if (strcmp(te->name, BLOB_XREF_TABLE) == 0)
return;
tblName = createPQExpBuffer();
tblQry = createPQExpBuffer();
appendPQExpBuffer(tblQry, "SELECT a.attname FROM pg_class c, pg_attribute a, pg_type t "
" WHERE a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid "
" AND t.typname in ('oid', 'lo') AND c.relname = '%s';", tablename);
if (te->namespace && strlen(te->namespace) > 0)
appendPQExpBuffer(tblName, "%s.",
fmtId(te->namespace, false));
appendPQExpBuffer(tblName, "%s",
fmtId(te->name, false));
appendPQExpBuffer(tblQry,
"SELECT a.attname FROM "
"pg_catalog.pg_attribute a, pg_catalog.pg_type t "
"WHERE a.attnum > 0 AND a.attrelid = '%s'::regclass "
"AND a.atttypid = t.oid AND t.typname in ('oid', 'lo')",
tblName->data);
res = PQexec(AH->blobConnection, tblQry->data);
if (!res)
die_horribly(AH, modulename, "could not find oid columns of table \"%s\": %s",
tablename, PQerrorMessage(AH->connection));
te->name, PQerrorMessage(AH->connection));
if ((n = PQntuples(res)) == 0)
{
/* nothing to do */
ahlog(AH, 1, "no OID type columns in table %s\n", tablename);
ahlog(AH, 1, "no OID type columns in table %s\n", te->name);
}
for (i = 0; i < n; i++)
{
attr = PQgetvalue(res, i, 0);
ahlog(AH, 1, "fixing large object cross-references for %s.%s\n", tablename, attr);
ahlog(AH, 1, "fixing large object cross-references for %s.%s\n",
te->name, attr);
resetPQExpBuffer(tblQry);
/*
* We should use coalesce here (rather than 'exists'), but it
* seems to be broken in 7.0.2 (weird optimizer strategy)
*/
appendPQExpBuffer(tblQry, "UPDATE \"%s\" SET \"%s\" = ", tablename, attr);
appendPQExpBuffer(tblQry, " (SELECT x.newOid FROM \"%s\" x WHERE x.oldOid = \"%s\".\"%s\")",
BLOB_XREF_TABLE, tablename, attr);
appendPQExpBuffer(tblQry, " where exists"
"(select * from %s x where x.oldOid = \"%s\".\"%s\");",
BLOB_XREF_TABLE, tablename, attr);
/* Can't use fmtId twice in one call... */
appendPQExpBuffer(tblQry,
"UPDATE %s SET %s = %s.newOid",
tblName->data, fmtId(attr, false),
BLOB_XREF_TABLE);
appendPQExpBuffer(tblQry,
" FROM %s WHERE %s.oldOid = %s.%s",
BLOB_XREF_TABLE,
BLOB_XREF_TABLE,
tblName->data, fmtId(attr, false));
ahlog(AH, 10, "SQL: %s\n", tblQry->data);
@ -829,17 +770,18 @@ FixupBlobRefs(ArchiveHandle *AH, char *tablename)
if (!uRes)
die_horribly(AH, modulename,
"could not update column \"%s\" of table \"%s\": %s",
attr, tablename, PQerrorMessage(AH->blobConnection));
attr, te->name, PQerrorMessage(AH->blobConnection));
if (PQresultStatus(uRes) != PGRES_COMMAND_OK)
die_horribly(AH, modulename,
"error while updating column \"%s\" of table \"%s\": %s",
attr, tablename, PQerrorMessage(AH->blobConnection));
attr, te->name, PQerrorMessage(AH->blobConnection));
PQclear(uRes);
}
PQclear(res);
destroyPQExpBuffer(tblName);
destroyPQExpBuffer(tblQry);
}

View File

@ -2,12 +2,12 @@
* Definitions for pg_backup_db.c
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.h,v 1.5 2001/06/27 21:21:37 petere Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.h,v 1.6 2002/05/10 22:36:26 tgl Exp $
*/
#define BLOB_XREF_TABLE "dump_blob_xref" /* MUST be lower case */
#define BLOB_XREF_TABLE "pg_dump_blob_xref" /* MUST be lower case */
extern void FixupBlobRefs(ArchiveHandle *AH, char *tablename);
extern void FixupBlobRefs(ArchiveHandle *AH, TocEntry *te);
extern int ExecuteSqlCommand(ArchiveHandle *AH, PQExpBuffer qry, char *desc, bool use_blob);
extern int ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qry, int bufLen);

View File

@ -3,7 +3,7 @@
* pg_backup_null.c
*
* Implementation of an archive that is never saved; it is used by
* pg_dump to output output a plain text SQL script instead of save
* pg_dump to output a plain text SQL script instead of save
* a real archive.
*
* See the headers to pg_restore for more details.
@ -17,7 +17,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.8 2002/04/24 02:21:04 momjian Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.9 2002/05/10 22:36:26 tgl Exp $
*
* Modifications - 09-Jul-2000 - pjw@rhyme.com.au
*

View File

@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.21 2002/04/24 02:21:04 momjian Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.22 2002/05/10 22:36:26 tgl Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
*
@ -835,7 +835,7 @@ _CloseArchive(ArchiveHandle *AH)
ropt = NewRestoreOptions();
ropt->dropSchema = 1;
ropt->compression = 0;
ropt->superuser = PQuser(AH->connection);
ropt->superuser = NULL;
ropt->suppressDumpWarnings = true;
savVerbose = AH->public.verbose;

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +1,12 @@
/*-------------------------------------------------------------------------
*
* pg_dump.h
* header file for the pg_dump utility
* Common header file for the pg_dump utility
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_dump.h,v 1.84 2002/04/24 22:39:49 petere Exp $
*
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
*
* - Fixed dumpTable output to output lengths for char and varchar types!
* - Added single. quote to twin single quote expansion for 'insert' string
* mode.
*
* Modifications - 6/1/97 - igor@sba.miami.edu
* - Added extern's for the functions that clear allocated memory
* in pg_dump.c
*
* Modifications - 14-Sep-2000 - pjw@rhyme.com.au
* - Added typedefn fields to typeinfo and relinfo
* - Added enum for findTypeByOid to allow special handling of
* '0' OID.
* $Id: pg_dump.h,v 1.85 2002/05/10 22:36:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,171 +17,133 @@
#include "pg_backup.h"
#include "pqexpbuffer.h"
/* The data structures used to store system catalog information */
/*
* The data structures used to store system catalog information
*
* NOTE: the structures described here live for the entire pg_dump run;
* and in most cases we make a struct for every object we can find in the
* catalogs, not only those we are actually going to dump. Hence, it's
* best to store a minimal amount of per-object info in these structs,
* and retrieve additional per-object info when and if we dump a specific
* object. In particular, try to avoid retrieving expensive-to-compute
* information until it's known to be needed.
*/
typedef struct _namespaceInfo
{
char *oid;
char *nspname;
char *usename; /* name of owner, or empty string */
char *nspacl;
bool dump; /* true if need to dump definition */
} NamespaceInfo;
typedef struct _typeInfo
{
char *oid;
char *typowner;
char *typname;
char *typlen;
char *typprtlen;
char *typinput;
char *typoutput;
char *typreceive;
char *typsend;
char *typelem;
char *typdelim;
char *typdefault;
char *typrelid;
char *typalign;
char *typstorage;
char *usename;
char *typedefn;
char *typtype;
int passedbyvalue;
int isArray;
int isDefined;
char *typname; /* name as seen in catalog */
/* Note: format_type might produce something different than typname */
NamespaceInfo *typnamespace; /* link to containing namespace */
char *usename; /* name of owner, or empty string */
char *typelem; /* OID */
char *typrelid; /* OID */
char typtype; /* 'b', 'c', etc */
bool isArray; /* true if user-defined array type */
bool isDefined; /* true if typisdefined */
} TypeInfo;
typedef struct _funcInfo
{
char *oid;
char *proname;
char *proowner;
NamespaceInfo *pronamespace; /* link to containing namespace */
char *usename; /* name of owner, or empty string */
Oid lang;
int nargs;
char **argtypes;
char *prorettype;
int retset; /* 1 if the function returns a set, else 0 */
char *prosrc;
char *probin;
char *usename;
char provolatile; /* Attr */
bool isimplicit; /* Attr */
bool isstrict; /* Attr */
int dumped; /* 1 if already dumped */
char **argtypes; /* OIDs */
char *prorettype; /* OID */
bool dumped; /* true if already dumped */
} FuncInfo;
typedef struct _trigInfo
{
char *oid;
char *tgname;
char *tgsrc;
char *tgdel;
char *tgcomment;
} TrigInfo;
typedef struct _tableInfo
{
char *oid;
char *relname;
char *relacl;
char *viewdef;
char *viewoid; /* OID of view - should be >= oid of table
* important because views may be
* constructed manually from rules, and
* rule may ref things created after the
* base table was created. */
char relkind;
bool hasindex; /* does it have any indexes? */
bool hasoids; /* does it have OIDs? */
int numatts; /* number of attributes */
int *inhAttrs; /* an array of flags, one for each
* attribute if the value is 1, then this
* attribute is an inherited attribute */
int *inhAttrDef; /* Flags indicating if attrdef is
* inherited */
int *inhNotNull; /* Flags indicating if NOT NULL in
* inherited */
char **attnames; /* the attribute names */
char **atttypedefns; /* formatted column type definitions */
char **typnames; /* fill out attributes */
bool *notnull; /* Not null constraints of an attribute */
char **adef_expr; /* DEFAULT expressions */
int numParents; /* number of (immediate) parent
* supertables */
char **parentRels; /* names of parent relations, NULL if
* numParents == 0 */
char **out_attnames; /* the attribute names, in the order they
* would be in, when the table is created
* in the target query language. this is
* needed because the SQL tables will not
* have the same order of attributes as
* the POSTQUEL tables */
int *atttypmod; /* type-specific type modifier */
char *usename;
int ncheck; /* # of CHECK expressions */
char **check_expr; /* [CONSTRAINT name] CHECK expressions */
int ntrig; /* # of triggers */
TrigInfo *triggers; /* Triggers on the table */
char *pkIndexOid; /* Primary Key index OID */
char *primary_key_name; /* PRIMARY KEY name, if any */
} TableInfo;
typedef struct _inhInfo
{
char *inhrelid;
char *inhparent;
} InhInfo;
typedef struct _indInfo
{
char *indexreloid; /* oid of the index itself */
char *indreloid; /* oid of the table the index is on */
char *indexrelname; /* name of the index itself */
char *indrelname; /* name of the indexed table */
char *indexdef; /* index definitional command */
char *indisprimary; /* is this a PK index? */
int indnkeys; /* number of keys in index */
char **indkey; /* attribute numbers of the key
* attributes */
} IndInfo;
typedef struct _aggInfo
{
char *oid;
char *aggname;
char *aggtransfn;
char *aggfinalfn;
char *aggtranstype;
char *aggbasetype;
char *agginitval;
NamespaceInfo *aggnamespace; /* link to containing namespace */
char *usename;
int convertok; /* Flag to indicate of version convertsion
* is OK */
} AggInfo;
typedef struct _oprInfo
{
char *oid;
char *oprname;
char *oprkind; /*----------
* b = binary,
* l = left unary
* r = right unary
*----------
*/
char *oprcode; /* operator function name */
char *oprleft; /* left operand type */
char *oprright; /* right operand type */
char *oprcom; /* oid of the commutator operator */
char *oprnegate; /* oid of the negator operator */
char *oprrest; /* name of the function to calculate
* operator restriction selectivity */
char *oprjoin; /* name of the function to calculate
* operator join selectivity */
char *oprcanhash; /* can we use hash join strategy ? */
char *oprlsortop; /* oid's of the left and right sort
* operators */
char *oprrsortop;
NamespaceInfo *oprnamespace; /* link to containing namespace */
char *usename;
char *oprcode; /* as OID, not regproc name */
} OprInfo;
typedef struct _tableInfo
{
/*
* These fields are collected for every table in the database.
*/
char *oid;
char *relname;
NamespaceInfo *relnamespace; /* link to containing namespace */
char *usename; /* name of owner, or empty string */
char *relacl;
char relkind;
bool hasindex; /* does it have any indexes? */
bool hasrules; /* does it have any rules? */
bool hasoids; /* does it have OIDs? */
int ncheck; /* # of CHECK expressions */
int ntrig; /* # of triggers */
bool interesting; /* true if need to collect more data */
bool dump; /* true if we want to dump it */
/*
* These fields are computed only if we decide the table is interesting
* (it's either a table to dump, or a direct parent of a dumpable table).
*/
int numatts; /* number of attributes */
char **attnames; /* the attribute names */
char **atttypnames; /* attribute type names */
int *atttypmod; /* type-specific type modifiers */
/*
* Note: we need to store per-attribute notnull and default stuff for
* all interesting tables so that we can tell which constraints were
* inherited.
*/
bool *notnull; /* Not null constraints on attributes */
char **adef_expr; /* DEFAULT expressions */
bool *inhAttrs; /* true if each attribute is inherited */
bool *inhAttrDef; /* true if attr's default is inherited */
bool *inhNotNull; /* true if NOT NULL is inherited */
/*
* Stuff computed only for dumpable tables.
*/
int numParents; /* number of (immediate) parent tables */
int *parentIndexes; /* TableInfo indexes of immediate parents */
char *viewoid; /* OID of view - should be >= oid of table
* important because views may be
* constructed manually from rules, and
* rule may ref things created after the
* base table was created. */
} TableInfo;
typedef struct _inhInfo
{
char *inhrelid; /* OID of a child table */
char *inhparent; /* OID of its parent */
} InhInfo;
/* global decls */
extern bool force_quotes; /* double-quotes for identifiers flag */
extern bool g_verbose; /* verbose flag */
extern Oid g_last_builtin_oid; /* value of the last builtin oid */
extern Archive *g_fout; /* the script file */
/* placeholders for comment starting and ending delimiters */
@ -212,73 +159,55 @@ extern char g_opaque_type[10]; /* name for the opaque type */
*/
/*
* common utility functions
*/
*/
extern TableInfo *dumpSchema(Archive *fout,
int *numTablesPtr,
const char *tablename,
const bool acls,
const bool oids,
const bool aclsSkip,
const bool schemaOnly,
const bool dataOnly);
extern void dumpSchemaIdx(Archive *fout,
const char *tablename,
TableInfo *tblinfo,
int numTables);
typedef enum _OidOptions
{
zeroAsOpaque = 1,
zeroAsAny = 2,
zeroAsStar = 4,
zeroAsNone = 8,
useBaseTypeName = 1024
zeroAsNone = 8
} OidOptions;
extern char *findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts);
extern int findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
extern char *findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid);
extern int findFuncByName(FuncInfo *finfo, int numFuncs, const char *name);
extern int findTableByName(TableInfo *tbinfo, int numTables, const char *relname);
extern int findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid);
extern void check_conn_and_db(void);
extern void exit_nicely(void);
extern void parseNumericArray(const char *str, char **array, int arraysize);
/*
* version specific routines
*/
extern NamespaceInfo *getNamespaces(int *numNamespaces);
extern TypeInfo *getTypes(int *numTypes);
extern FuncInfo *getFuncs(int *numFuncs);
extern AggInfo *getAggregates(int *numAggregates);
extern void clearAggInfo(AggInfo *, int);
extern void clearFuncInfo(FuncInfo *, int);
extern void clearInhInfo(InhInfo *, int);
extern void clearIndInfo(IndInfo *, int);
extern void clearOprInfo(OprInfo *, int);
extern void clearTypeInfo(TypeInfo *, int);
extern OprInfo *getOperators(int *numOperators);
extern TableInfo *getTables(int *numTables, FuncInfo *finfo, int numFuncs,
const char* tablename);
extern TableInfo *getTables(int *numTables);
extern InhInfo *getInherits(int *numInherits);
extern void getTableAttrs(TableInfo *tbinfo, int numTables);
extern IndInfo *getIndexes(int *numIndexes);
extern void dumpDBComment(Archive *outfile);
extern void dumpNamespaces(Archive *fout,
NamespaceInfo *nsinfo, int numNamespaces);
extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
TypeInfo *tinfo, int numTypes);
extern void dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
TypeInfo *tinfo, int numTypes);
extern void dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs,
TypeInfo *tinfo, int numTypes);
extern void dumpAggs(Archive *fout, AggInfo *agginfo, int numAggregates,
TypeInfo *tinfo, int numTypes);
extern void dumpOprs(Archive *fout, OprInfo *agginfo, int numOperators,
TypeInfo *tinfo, int numTypes);
extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables,
const char *tablename, const bool acls,
const bool schemaOnly, const bool dataOnly);
extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
TableInfo *tbinfo, int numTables, const char *tablename);
extern void exit_nicely(void);
extern void dumpProcLangs(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 dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
extern void dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
const bool aclsSkip,
const bool schemaOnly, const bool dataOnly);
extern void dumpIndexes(Archive *fout, TableInfo *tbinfo, int numTables);
#endif /* PG_DUMP_H */

View File

@ -34,22 +34,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.33 2002/01/18 19:17:05 momjian Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
*
* Initial version. Command processing taken from original pg_dump.
*
* Modifications - 28-Jul-2000 - pjw@rhyme.com.au (1.45)
*
* Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
* Added code to dump 'Create Schema' statement (pg_dump)
* Don't bother to disable/enable triggers if we don't have a superuser (pg_restore)
* Cleaned up code for reconnecting to database.
* Force a reconnect as superuser before enabling/disabling triggers.
*
* Modifications - 6-Mar-2001 - pjw@rhyme.com.au
* Change -U option to -L to allow -U to specify username in future.
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.34 2002/05/10 22:36:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -94,6 +79,7 @@ main(int argc, char **argv)
extern int optind;
extern char *optarg;
static int use_setsessauth = 0;
static int disable_triggers = 0;
#ifdef HAVE_GETOPT_LONG
struct option cmdopts[] = {
@ -130,6 +116,8 @@ main(int argc, char **argv)
* letter, but are available as '-X long-name'
*/
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{"disable-triggers", no_argument, &disable_triggers, 1},
{NULL, 0, NULL, 0}
};
#endif /* HAVE_GETOPT_LONG */
@ -281,6 +269,8 @@ main(int argc, char **argv)
case 'X':
if (strcmp(optarg, "use-set-session-authorization") == 0)
use_setsessauth = 1;
else if (strcmp(optarg, "disable-triggers") == 0)
disable_triggers = 1;
else
{
fprintf(stderr,
@ -309,6 +299,7 @@ main(int argc, char **argv)
fileSpec = NULL;
opts->use_setsessauth = use_setsessauth;
opts->disable_triggers = disable_triggers;
if (opts->formatName)
{
@ -385,74 +376,77 @@ usage(const char *progname)
progname, progname);
#ifdef HAVE_GETOPT_LONG
puts(gettext(
" -a, --data-only restore only the data, no schema\n"
" -c, --clean clean (drop) schema prior to create\n"
" -C, --create issue commands to create the database\n"
" -d, --dbname=NAME output database name\n"
" -f, --file=FILENAME output file name\n"
" -F, --format={c|t} specify backup file format\n"
" -h, --host=HOSTNAME server host name\n"
" -i, --index=NAME restore named index\n"
" -l, --list print summarized TOC of the archive\n"
" -L, --use-list=FILENAME use specified table of contents for ordering\n"
" output from this file\n"
" -N, --orig-order restore in original dump order\n"
" -o, --oid-order restore in OID order\n"
" -O, --no-owner do not reconnect to database to match\n"
" object owner\n"
" -p, --port=PORT server port number\n"
" -P, --function=NAME restore named function\n"
" -r, --rearrange rearrange output to put indexes etc. at end\n"
" -R, --no-reconnect disallow ALL reconnections to the database\n"
" -s, --schema-only restore only the schema, no data\n"
" -S, --superuser=NAME specify the superuser user name to use for\n"
" disabling triggers\n"
" -t, --table=NAME restore named table\n"
" -T, --trigger=NAME restore named trigger\n"
" -a, --data-only restore only the data, no schema\n"
" -c, --clean clean (drop) schema prior to create\n"
" -C, --create issue commands to create the database\n"
" -d, --dbname=NAME output database name\n"
" -f, --file=FILENAME output file name\n"
" -F, --format={c|t} specify backup file format\n"
" -h, --host=HOSTNAME server host name\n"
" -i, --index=NAME restore named index\n"
" -l, --list print summarized TOC of the archive\n"
" -L, --use-list=FILENAME use specified table of contents for ordering\n"
" output from this file\n"
" -N, --orig-order restore in original dump order\n"
" -o, --oid-order restore in OID order\n"
" -O, --no-owner do not reconnect to database to match\n"
" object owner\n"
" -p, --port=PORT server port number\n"
" -P, --function=NAME restore named function\n"
" -r, --rearrange rearrange output to put indexes etc. at end\n"
" -R, --no-reconnect disallow ALL reconnections to the database\n"
" -s, --schema-only restore only the schema, no data\n"
" -S, --superuser=NAME specify the superuser user name to use for\n"
" disabling triggers\n"
" -t, --table=NAME restore named table\n"
" -T, --trigger=NAME restore named trigger\n"
" -U, --username=NAME connect as specified database user\n"
" -v, --verbose verbose mode\n"
" -W, --password force password prompt (should happen automatically)\n"
" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n"
" -X use-set-session-authorization, --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead\n"
" of reconnecting, if possible\n"
));
" -v, --verbose verbose mode\n"
" -W, --password force password prompt (should happen automatically)\n"
" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n"
" -X use-set-session-authorization, --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead\n"
" of reconnecting, if possible\n"
" -X disable-triggers, --disable-triggers\n"
" disable triggers during data-only restore\n"
));
#else /* not HAVE_GETOPT_LONG */
puts(gettext(
" -a restore only the data, no schema\n"
" -c clean (drop) schema prior to create\n"
" -C issue commands to create the database\n"
" -d NAME output database name\n"
" -f FILENAME output file name\n"
" -F {c|t} specify backup file format\n"
" -h HOSTNAME server host name\n"
" -i NAME restore named index\n"
" -l print summarized TOC of the archive\n"
" -L FILENAME use specified table of contents for ordering\n"
" output from this file\n"
" -N restore in original dump order\n"
" -o restore in OID order\n"
" -O do not reconnect to database to match\n"
" object owner\n"
" -p PORT server port number\n"
" -P NAME restore named function\n"
" -r rearrange output to put indexes etc. at end\n"
" -R disallow ALL reconnections to the database\n"
" -s restore only the schema, no data\n"
" -S NAME specify the superuser user name to use for\n"
" disabling triggers\n"
" -t NAME restore named table\n"
" -T NAME restore named trigger\n"
" -a restore only the data, no schema\n"
" -c clean (drop) schema prior to create\n"
" -C issue commands to create the database\n"
" -d NAME output database name\n"
" -f FILENAME output file name\n"
" -F {c|t} specify backup file format\n"
" -h HOSTNAME server host name\n"
" -i NAME restore named index\n"
" -l print summarized TOC of the archive\n"
" -L FILENAME use specified table of contents for ordering\n"
" output from this file\n"
" -N restore in original dump order\n"
" -o restore in OID order\n"
" -O do not reconnect to database to match\n"
" object owner\n"
" -p PORT server port number\n"
" -P NAME restore named function\n"
" -r rearrange output to put indexes etc. at end\n"
" -R disallow ALL reconnections to the database\n"
" -s restore only the schema, no data\n"
" -S NAME specify the superuser user name to use for\n"
" disabling triggers\n"
" -t NAME restore named table\n"
" -T NAME restore named trigger\n"
" -U NAME connect as specified database user\n"
" -v verbose mode\n"
" -W force password prompt (should happen automatically)\n"
" -x skip restoration of access privileges (grant/revoke)\n"
" -X use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead\n"
" of reconnecting, if possible\n"
));
" -v verbose mode\n"
" -W force password prompt (should happen automatically)\n"
" -x skip restoration of access privileges (grant/revoke)\n"
" -X use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead\n"
" of reconnecting, if possible\n"
" -X disable-triggers disable triggers during data-only restore\n"
));
#endif
puts(gettext("If no input file name is supplied, then standard input is used.\n"));
puts(gettext("Report bugs to <pgsql-bugs@postgresql.org>."));