|
|
|
|
@ -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,255 +29,48 @@ |
|
|
|
|
#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 |
|
|
|
|
* |
|
|
|
|
* Can return various special cases for oid 0. |
|
|
|
|
* |
|
|
|
|
* NOTE: should hash this, but just do linear search for now |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
char * |
|
|
|
|
findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (strcmp(oid, "0") == 0) |
|
|
|
|
{ |
|
|
|
|
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"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numTypes; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(tinfo[i].oid, oid) == 0) |
|
|
|
|
{ |
|
|
|
|
if ((opts & useBaseTypeName) != 0) |
|
|
|
|
return (char *) fmtId(tinfo[i].typname, false); |
|
|
|
|
else |
|
|
|
|
return tinfo[i].typedefn; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* no suitable type name was found */ |
|
|
|
|
return (NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numOprs; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(oprinfo[i].oid, oid) == 0) |
|
|
|
|
return oprinfo[i].oprname; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* should never get here */ |
|
|
|
|
write_msg(NULL, "failed sanity check, operator with oid %s not found\n", oid); |
|
|
|
|
|
|
|
|
|
/* no suitable operator name was found */ |
|
|
|
|
return (NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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. |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* returns NULL if none |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static char ** |
|
|
|
|
findParentsByOid(TableInfo *tblinfo, int numTables, |
|
|
|
|
InhInfo *inhinfo, int numInherits, const char *oid, |
|
|
|
|
int *numParentsPtr, int (**parentIndexes)[]) |
|
|
|
|
{ |
|
|
|
|
int i, |
|
|
|
|
j; |
|
|
|
|
int parentInd, |
|
|
|
|
selfInd; |
|
|
|
|
char **result; |
|
|
|
|
int numParents; |
|
|
|
|
|
|
|
|
|
numParents = 0; |
|
|
|
|
for (i = 0; i < numInherits; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0) |
|
|
|
|
numParents++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*numParentsPtr = numParents; |
|
|
|
|
|
|
|
|
|
if (numParents > 0) |
|
|
|
|
{ |
|
|
|
|
result = (char **) malloc(sizeof(char *) * numParents); |
|
|
|
|
(*parentIndexes) = malloc(sizeof(int) * numParents); |
|
|
|
|
j = 0; |
|
|
|
|
for (i = 0; i < numInherits; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0) |
|
|
|
|
{ |
|
|
|
|
parentInd = findTableByOid(tblinfo, numTables, |
|
|
|
|
inhinfo[i].inhparent); |
|
|
|
|
if (parentInd < 0) |
|
|
|
|
{ |
|
|
|
|
selfInd = findTableByOid(tblinfo, numTables, oid); |
|
|
|
|
if (selfInd >= 0) |
|
|
|
|
write_msg(NULL, "failed sanity check, parent oid %s of table %s (oid %s) not found\n", |
|
|
|
|
inhinfo[i].inhparent, |
|
|
|
|
tblinfo[selfInd].relname, |
|
|
|
|
oid); |
|
|
|
|
else |
|
|
|
|
write_msg(NULL, "failed sanity check, parent oid %s of table (oid %s) not found\n", |
|
|
|
|
inhinfo[i].inhparent, |
|
|
|
|
oid); |
|
|
|
|
|
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
(**parentIndexes)[j] = parentInd; |
|
|
|
|
result[j++] = tblinfo[parentInd].relname; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
(*parentIndexes) = NULL; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* parseNumericArray |
|
|
|
|
* parse a string of numbers delimited by spaces into a character array |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
parseNumericArray(const char *str, char **array, int arraysize) |
|
|
|
|
{ |
|
|
|
|
int j, |
|
|
|
|
argNum; |
|
|
|
|
char temp[100]; |
|
|
|
|
char s; |
|
|
|
|
|
|
|
|
|
argNum = 0; |
|
|
|
|
j = 0; |
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
s = *str++; |
|
|
|
|
if (s == ' ' || s == '\0') |
|
|
|
|
{ |
|
|
|
|
if (j > 0) |
|
|
|
|
{ |
|
|
|
|
if (argNum >= arraysize) |
|
|
|
|
{ |
|
|
|
|
write_msg(NULL, "parseNumericArray: too many numbers\n"); |
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
temp[j] = '\0'; |
|
|
|
|
array[argNum++] = strdup(temp); |
|
|
|
|
j = 0; |
|
|
|
|
} |
|
|
|
|
if (s == '\0') |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (!(isdigit((unsigned char) s) || s == '-') || |
|
|
|
|
j >= sizeof(temp) - 1) |
|
|
|
|
{ |
|
|
|
|
write_msg(NULL, "parseNumericArray: bogus number\n"); |
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
temp[j++] = s; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (argNum < arraysize) |
|
|
|
|
array[argNum++] = strdup("0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* strInArray: |
|
|
|
|
* 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 |
|
|
|
|
strInArray(const char *pattern, char **arr, int arr_size) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < arr_size; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(pattern, arr[i]) == 0) |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
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 numNamespaces; |
|
|
|
|
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; |
|
|
|
|
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"); |
|
|
|
|
@ -312,32 +90,40 @@ dumpSchema(Archive *fout, |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
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 the column names and types for each table\n"); |
|
|
|
|
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 (!tablename && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out database comment\n"); |
|
|
|
|
dumpDBComment(fout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!tablename && 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"); |
|
|
|
|
@ -346,63 +132,102 @@ dumpSchema(Archive *fout, |
|
|
|
|
|
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out tables\n"); |
|
|
|
|
|
|
|
|
|
dumpTables(fout, tblinfo, numTables, tablename, |
|
|
|
|
dumpTables(fout, tblinfo, numTables, |
|
|
|
|
aclsSkip, schemaOnly, dataOnly); |
|
|
|
|
|
|
|
|
|
if (fout && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out indexes\n"); |
|
|
|
|
dumpIndexes(fout, indinfo, numIndexes, tblinfo, numTables, tablename); |
|
|
|
|
dumpIndexes(fout, tblinfo, numTables); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!tablename && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out user-defined procedural languages\n"); |
|
|
|
|
dumpProcLangs(fout, finfo, numFuncs, tinfo, numTypes); |
|
|
|
|
dumpProcLangs(fout, finfo, numFuncs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!tablename && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out user-defined functions\n"); |
|
|
|
|
dumpFuncs(fout, finfo, numFuncs, tinfo, numTypes); |
|
|
|
|
dumpFuncs(fout, finfo, numFuncs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!tablename && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out user-defined aggregate functions\n"); |
|
|
|
|
dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes); |
|
|
|
|
dumpAggs(fout, agginfo, numAggregates); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!tablename && !dataOnly) |
|
|
|
|
if (!dataOnly) |
|
|
|
|
{ |
|
|
|
|
if (g_verbose) |
|
|
|
|
write_msg(NULL, "dumping out user-defined operators\n"); |
|
|
|
|
dumpOprs(fout, oprinfo, numOperators, tinfo, numTypes); |
|
|
|
|
dumpOprs(fout, oprinfo, numOperators); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*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 |
|
|
|
|
/* flagInhTables -
|
|
|
|
|
* Fill in parentIndexes fields of every target table, and mark |
|
|
|
|
* parents of target tables as interesting |
|
|
|
|
* |
|
|
|
|
* initializes the parentRels field of each table |
|
|
|
|
* 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, |
|
|
|
|
@ -413,7 +238,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
k; |
|
|
|
|
int parentInd; |
|
|
|
|
int inhAttrInd; |
|
|
|
|
int (*parentIndexes)[]; |
|
|
|
|
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 */ |
|
|
|
|
@ -421,23 +247,22 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
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--) |
|
|
|
|
for (i = 0; i < numTables; i++) |
|
|
|
|
{ |
|
|
|
|
/* Sequences can never have parents, and attr info is undefined */ |
|
|
|
|
if (tblinfo[i].relkind == RELKIND_SEQUENCE) |
|
|
|
|
/* 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; |
|
|
|
|
|
|
|
|
|
/* Get all the parents and their indexes. */ |
|
|
|
|
tblinfo[i].parentRels = findParentsByOid(tblinfo, numTables, |
|
|
|
|
inhinfo, numInherits, |
|
|
|
|
tblinfo[i].oid, |
|
|
|
|
&tblinfo[i].numParents, |
|
|
|
|
&parentIndexes); |
|
|
|
|
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 |
|
|
|
|
@ -459,18 +284,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
|
|
|
|
|
attrDef = tblinfo[i].adef_expr[j]; |
|
|
|
|
|
|
|
|
|
for (k = 0; k < tblinfo[i].numParents; k++) |
|
|
|
|
for (k = 0; k < 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(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
parentInd = parentIndexes[k]; |
|
|
|
|
inhAttrInd = strInArray(tblinfo[i].attnames[j], |
|
|
|
|
tblinfo[parentInd].attnames, |
|
|
|
|
tblinfo[parentInd].numatts); |
|
|
|
|
@ -479,7 +295,7 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
{ |
|
|
|
|
foundAttr = true; |
|
|
|
|
foundNotNull |= tblinfo[parentInd].notnull[inhAttrInd]; |
|
|
|
|
if (attrDef != NULL) /* It we have a default,
|
|
|
|
|
if (attrDef != NULL) /* If we have a default,
|
|
|
|
|
* check parent */ |
|
|
|
|
{ |
|
|
|
|
inhDef = tblinfo[parentInd].adef_expr[inhAttrInd]; |
|
|
|
|
@ -488,10 +304,10 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
{ |
|
|
|
|
defaultsFound = true; |
|
|
|
|
defaultsMatch &= (strcmp(attrDef, inhDef) == 0); |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Based on the scan of the parents, decide if we can rely on |
|
|
|
|
@ -500,9 +316,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
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; |
|
|
|
|
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 |
|
|
|
|
@ -510,8 +326,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
*/ |
|
|
|
|
if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch)) |
|
|
|
|
{ |
|
|
|
|
tblinfo[i].inhAttrs[j] = 0; |
|
|
|
|
tblinfo[i].inhAttrDef[j] = 0; |
|
|
|
|
tblinfo[i].inhAttrs[j] = false; |
|
|
|
|
tblinfo[i].inhAttrDef[j] = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -520,8 +336,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
*/ |
|
|
|
|
if (tblinfo[i].notnull[j] && !foundNotNull) |
|
|
|
|
{ |
|
|
|
|
tblinfo[i].inhAttrs[j] = 0; |
|
|
|
|
tblinfo[i].inhNotNull[j] = 0; |
|
|
|
|
tblinfo[i].inhAttrs[j] = false; |
|
|
|
|
tblinfo[i].inhNotNull[j] = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -530,64 +346,199 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* findTableByName |
|
|
|
|
* finds the index (in tblinfo) of the table with the given relname |
|
|
|
|
* 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 |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
findTableByName(TableInfo *tblinfo, int numTables, const char *relname) |
|
|
|
|
findTableByOid(TableInfo *tblinfo, int numTables, const char *oid) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numTables; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(tblinfo[i].relname, relname) == 0) |
|
|
|
|
if (strcmp(tblinfo[i].oid, oid) == 0) |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* findTableByOid |
|
|
|
|
* finds the index (in tblinfo) of the table with the given oid |
|
|
|
|
* 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 |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
findTableByOid(TableInfo *tblinfo, int numTables, const char *oid) |
|
|
|
|
int |
|
|
|
|
findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numTables; i++) |
|
|
|
|
for (i = 0; i < numFuncs; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(tblinfo[i].oid, oid) == 0) |
|
|
|
|
if (strcmp(finfo[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 |
|
|
|
|
* 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) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
findFuncByName(FuncInfo *finfo, int numFuncs, const char *name) |
|
|
|
|
for (i = 0; i < numOprs; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(oprinfo[i].oid, oid) == 0) |
|
|
|
|
return oprinfo[i].oprname; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* should never get here */ |
|
|
|
|
write_msg(NULL, "failed sanity check, operator with oid %s not found\n", oid); |
|
|
|
|
|
|
|
|
|
/* no suitable operator name was found */ |
|
|
|
|
return (NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* findParentsByOid |
|
|
|
|
* given the oid of a class, find its parent classes in tblinfo[] |
|
|
|
|
* |
|
|
|
|
* Returns the number of parents and their array indexes into the |
|
|
|
|
* last two arguments. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
findParentsByOid(TableInfo *tblinfo, int numTables, |
|
|
|
|
InhInfo *inhinfo, int numInherits, |
|
|
|
|
const char *oid, |
|
|
|
|
int *numParentsPtr, int **parentIndexes) |
|
|
|
|
{ |
|
|
|
|
int i, |
|
|
|
|
j; |
|
|
|
|
int parentInd, |
|
|
|
|
selfInd; |
|
|
|
|
int numParents; |
|
|
|
|
|
|
|
|
|
numParents = 0; |
|
|
|
|
for (i = 0; i < numInherits; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0) |
|
|
|
|
numParents++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*numParentsPtr = numParents; |
|
|
|
|
|
|
|
|
|
if (numParents > 0) |
|
|
|
|
{ |
|
|
|
|
*parentIndexes = (int *) malloc(sizeof(int) * numParents); |
|
|
|
|
j = 0; |
|
|
|
|
for (i = 0; i < numInherits; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0) |
|
|
|
|
{ |
|
|
|
|
parentInd = findTableByOid(tblinfo, numTables, |
|
|
|
|
inhinfo[i].inhparent); |
|
|
|
|
if (parentInd < 0) |
|
|
|
|
{ |
|
|
|
|
selfInd = findTableByOid(tblinfo, numTables, oid); |
|
|
|
|
if (selfInd >= 0) |
|
|
|
|
write_msg(NULL, "failed sanity check, parent oid %s of table %s (oid %s) not found\n", |
|
|
|
|
inhinfo[i].inhparent, |
|
|
|
|
tblinfo[selfInd].relname, |
|
|
|
|
oid); |
|
|
|
|
else |
|
|
|
|
write_msg(NULL, "failed sanity check, parent oid %s of table (oid %s) not found\n", |
|
|
|
|
inhinfo[i].inhparent, |
|
|
|
|
oid); |
|
|
|
|
|
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
(*parentIndexes)[j++] = parentInd; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
*parentIndexes = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* parseNumericArray |
|
|
|
|
* parse a string of numbers delimited by spaces into a character array |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
parseNumericArray(const char *str, char **array, int arraysize) |
|
|
|
|
{ |
|
|
|
|
int j, |
|
|
|
|
argNum; |
|
|
|
|
char temp[100]; |
|
|
|
|
char s; |
|
|
|
|
|
|
|
|
|
argNum = 0; |
|
|
|
|
j = 0; |
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
s = *str++; |
|
|
|
|
if (s == ' ' || s == '\0') |
|
|
|
|
{ |
|
|
|
|
if (j > 0) |
|
|
|
|
{ |
|
|
|
|
if (argNum >= arraysize) |
|
|
|
|
{ |
|
|
|
|
write_msg(NULL, "parseNumericArray: too many numbers\n"); |
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
temp[j] = '\0'; |
|
|
|
|
array[argNum++] = strdup(temp); |
|
|
|
|
j = 0; |
|
|
|
|
} |
|
|
|
|
if (s == '\0') |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (!(isdigit((unsigned char) s) || s == '-') || |
|
|
|
|
j >= sizeof(temp) - 1) |
|
|
|
|
{ |
|
|
|
|
write_msg(NULL, "parseNumericArray: bogus number\n"); |
|
|
|
|
exit_nicely(); |
|
|
|
|
} |
|
|
|
|
temp[j++] = s; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (argNum < arraysize) |
|
|
|
|
array[argNum++] = strdup("0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* strInArray: |
|
|
|
|
* 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 |
|
|
|
|
strInArray(const char *pattern, char **arr, int arr_size) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numFuncs; i++) |
|
|
|
|
for (i = 0; i < arr_size; i++) |
|
|
|
|
{ |
|
|
|
|
if (strcmp(finfo[i].proname, name) == 0) |
|
|
|
|
if (strcmp(pattern, arr[i]) == 0) |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
return -1; |
|
|
|
|
|