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

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.44 2002/04/21 19:02:39 thomas Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.45 2002/05/10 22:36:26 tgl Exp $
PostgreSQL documentation
-->
@ -407,10 +407,11 @@ PostgreSQL documentation
<term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
<listitem>
<para>
The scripts or archives created by <command>pg_dump</command>
need to have superuser access in certain cases, such as when
disabling triggers or setting ownership of schema elements.
This option specifies the user name to use for those cases.
Specify the superuser user name to use when disabling triggers.
This is only relevant if <option>--disable-triggers</> is used.
(Usually, it's better to specify
<option>--use-set-session-authorization</>, and then start the
resulting script as superuser.)
</para>
</listitem>
</varlistentry>
@ -481,6 +482,36 @@ PostgreSQL documentation
</listitem>
</varlistentry>
<varlistentry>
<term><option>-X disable-triggers</></term>
<term><option>--disable-triggers</></term>
<listitem>
<para>
This option is only relevant when creating a data-only dump.
It instructs <command>pg_dump</command> to include commands
to temporarily disable triggers on the target tables while
the data is reloaded. Use this if you have referential
integrity checks or other triggers on the tables that you
do not want to invoke during data reload.
</para>
<para>
Presently, the commands emitted for <option>--disable-triggers</>
must be done as superuser. So, you should also specify
a superuser name with <option>-S</>, or preferably specify
<option>--use-set-session-authorization</> and then be careful to
start the resulting script as a superuser. If you give neither
option, the entire script must be run as superuser.
</para>
<para>
This option is only meaningful for the plain-text format. For
the other formats, you may specify the option when you
call <command>pg_restore</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-Z <replaceable class="parameter">0..9</replaceable></option></term>
<term><option>--compress=<replaceable class="parameter">0..9</replaceable></option></term>

View File

@ -1,4 +1,4 @@
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.24 2002/04/21 19:02:39 thomas Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.25 2002/05/10 22:36:26 tgl Exp $ -->
<refentry id="APP-PGRESTORE">
<docinfo>
@ -336,8 +336,8 @@
<term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
<listitem>
<para>
Specify the superuser user name to use when disabling triggers and/or setting ownership of schema elements.
By default, <COMMAND>pg_restore</COMMAND> will use the current user name if it is a superuser.
Specify the superuser user name to use when disabling triggers.
This is only relevant if <option>--disable-triggers</> is used.
</para>
</listitem>
</varlistentry>
@ -402,6 +402,29 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-X disable-triggers</></term>
<term><option>--disable-triggers</></term>
<listitem>
<para>
This option is only relevant when performing a data-only restore.
It instructs <command>pg_restore</command> to execute commands
to temporarily disable triggers on the target tables while
the data is reloaded. Use this if you have referential
integrity checks or other triggers on the tables that you
do not want to invoke during data reload.
</para>
<para>
Presently, the commands emitted for <option>--disable-triggers</>
must be done as superuser. So, you should also specify
a superuser name with <option>-S</>, or preferably specify
<option>--use-set-session-authorization</> and run
<command>pg_restore</command> as a superuser.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>

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>."));