mirror of https://github.com/postgres/postgres
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:
parent
1011fb651d
commit
9f0ae0c820
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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>."));
|
||||
|
|
Loading…
Reference in New Issue