1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* common.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* common routines between pg_dump and pg4_dump
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-09-15 06:57:09 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.47 2000/09/15 04:57:09 pjw Exp $
|
1996-07-22 10:37:00 +02:00
|
|
|
*
|
|
|
|
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
|
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* - Fixed dumpTable output to output lengths for char and varchar types!
|
|
|
|
* - Added single. quote to twin single quote expansion for 'insert' string
|
|
|
|
* mode.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-09-15 06:35:16 +02:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* BEWARE: Since fmtId uses a static buffer, using 'useBaseTypeName' on more
|
|
|
|
* than one call in a line will cause problems.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
1997-10-30 17:48:03 +01:00
|
|
|
#include <ctype.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#include "postgres.h"
|
1999-10-23 05:13:33 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "libpq-fe.h"
|
1997-02-13 09:32:20 +01:00
|
|
|
#ifndef HAVE_STRDUP
|
1996-11-26 08:39:11 +01:00
|
|
|
#include "strdup.h"
|
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#include "pg_dump.h"
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
static char **findParentsByOid(TableInfo *tbinfo, int numTables,
|
1997-09-08 23:56:23 +02:00
|
|
|
InhInfo *inhinfo, int numInherits,
|
1997-09-07 07:04:48 +02:00
|
|
|
const char *oid,
|
|
|
|
int *numParents);
|
1997-09-08 23:56:23 +02:00
|
|
|
static int findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
|
1998-09-01 06:40:42 +02:00
|
|
|
static void flagInhAttrs(TableInfo *tbinfo, int numTables,
|
1997-09-08 23:56:23 +02:00
|
|
|
InhInfo *inhinfo, int numInherits);
|
1997-09-08 04:41:22 +02:00
|
|
|
static int strInArray(const char *pattern, char **arr, int arr_size);
|
1997-08-19 23:40:56 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* findTypeByOid
|
|
|
|
* given an oid of a type, return its typename
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* if oid is "0", return "opaque" -- this is a special case
|
|
|
|
*
|
|
|
|
* NOTE: should hash this, but just do linear search for now
|
|
|
|
*/
|
|
|
|
|
1998-02-26 05:46:47 +01:00
|
|
|
char *
|
2000-09-15 06:35:16 +02:00
|
|
|
findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-09-15 06:35:16 +02:00
|
|
|
if (strcmp(oid, "0") == 0) {
|
|
|
|
|
|
|
|
if ( (opts & zeroAsOpaque) != 0 ) {
|
|
|
|
|
|
|
|
return g_opaque_type;
|
|
|
|
|
|
|
|
} else if ( (opts & zeroAsAny) != 0 ) {
|
|
|
|
|
|
|
|
return "'any'";
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = 0; i < numTypes; i++)
|
|
|
|
{
|
2000-09-15 06:35:16 +02:00
|
|
|
if (strcmp(tinfo[i].oid, oid) == 0) {
|
|
|
|
if ( (opts & useBaseTypeName) != 0 ) {
|
2000-09-15 06:57:09 +02:00
|
|
|
return (char*) fmtId(tinfo[i].typname, false);
|
2000-09-15 06:35:16 +02:00
|
|
|
} else {
|
|
|
|
return tinfo[i].typedefn;
|
|
|
|
}
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/* should never get here */
|
2000-01-18 08:29:58 +01:00
|
|
|
fprintf(stderr, "failed sanity check, type with oid %s was not found\n",
|
1997-09-07 07:04:48 +02:00
|
|
|
oid);
|
|
|
|
exit(2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* findOprByOid
|
1997-09-07 07:04:48 +02:00
|
|
|
* given the oid of an operator, return the name of the operator
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* NOTE: should hash this, but just do linear search for now
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
char *
|
1997-09-08 23:56:23 +02:00
|
|
|
findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < numOprs; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(oprinfo[i].oid, oid) == 0)
|
|
|
|
return oprinfo[i].oprname;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* should never get here */
|
2000-01-18 08:29:58 +01:00
|
|
|
fprintf(stderr, "failed sanity check, opr with oid %s was not found\n",
|
1997-09-07 07:04:48 +02:00
|
|
|
oid);
|
|
|
|
exit(2);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* findParentsByOid
|
1997-09-07 07:04:48 +02:00
|
|
|
* given the oid of a class, return the names of its parent classes
|
1996-07-09 08:22:35 +02:00
|
|
|
* and assign the number of parents to the last argument.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* returns NULL if none
|
|
|
|
*/
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
static char **
|
1997-09-08 23:56:23 +02:00
|
|
|
findParentsByOid(TableInfo *tblinfo, int numTables,
|
|
|
|
InhInfo *inhinfo, int numInherits, const char *oid,
|
1997-09-07 07:04:48 +02:00
|
|
|
int *numParentsPtr)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i,
|
|
|
|
j;
|
1998-09-20 05:18:43 +02:00
|
|
|
int parentInd,
|
|
|
|
selfInd;
|
1997-09-08 04:41:22 +02:00
|
|
|
char **result;
|
|
|
|
int numParents;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
numParents = 0;
|
|
|
|
for (i = 0; i < numInherits; i++)
|
|
|
|
{
|
1999-11-22 18:56:41 +01:00
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0)
|
1997-09-07 07:04:48 +02:00
|
|
|
numParents++;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
*numParentsPtr = numParents;
|
|
|
|
|
|
|
|
if (numParents > 0)
|
|
|
|
{
|
|
|
|
result = (char **) malloc(sizeof(char *) * numParents);
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; i < numInherits; i++)
|
|
|
|
{
|
1999-11-22 18:56:41 +01:00
|
|
|
if (strcmp(inhinfo[i].inhrelid, oid) == 0)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
|
|
|
parentInd = findTableByOid(tblinfo, numTables,
|
|
|
|
inhinfo[i].inhparent);
|
1998-09-20 05:18:43 +02:00
|
|
|
if (parentInd < 0)
|
|
|
|
{
|
|
|
|
selfInd = findTableByOid(tblinfo, numTables, oid);
|
|
|
|
fprintf(stderr,
|
|
|
|
"failed sanity check, parent oid %s of table %s (oid %s) was not found\n",
|
|
|
|
inhinfo[i].inhparent,
|
1999-05-25 18:15:34 +02:00
|
|
|
(selfInd >= 0) ? tblinfo[selfInd].relname : "",
|
1998-09-20 05:18:43 +02:00
|
|
|
oid);
|
|
|
|
exit(2);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
result[j++] = tblinfo[parentInd].relname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
|
|
|
return NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-01-16 04:54:58 +01:00
|
|
|
* parseNumericArray
|
|
|
|
* parse a string of numbers delimited by spaces into a character array
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
void
|
2000-01-16 04:54:58 +01:00
|
|
|
parseNumericArray(const char *str, char **array, int arraysize)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int j,
|
|
|
|
argNum;
|
|
|
|
char temp[100];
|
|
|
|
char s;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
argNum = 0;
|
|
|
|
j = 0;
|
2000-01-16 04:54:58 +01:00
|
|
|
for (;;)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-01-16 04:54:58 +01:00
|
|
|
s = *str++;
|
|
|
|
if (s == ' ' || s == '\0')
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-01-16 04:54:58 +01:00
|
|
|
if (j > 0)
|
|
|
|
{
|
|
|
|
if (argNum >= arraysize)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "parseNumericArray: too many numbers\n");
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
temp[j] = '\0';
|
|
|
|
array[argNum++] = strdup(temp);
|
|
|
|
j = 0;
|
|
|
|
}
|
|
|
|
if (s == '\0')
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-14 20:18:01 +02:00
|
|
|
if (!(isdigit((int) s) || s == '-') || j >= sizeof(temp) - 1)
|
2000-01-16 04:54:58 +01:00
|
|
|
{
|
|
|
|
fprintf(stderr, "parseNumericArray: bogus number\n");
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
temp[j++] = s;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
}
|
2000-01-16 04:54:58 +01:00
|
|
|
while (argNum < arraysize)
|
|
|
|
array[argNum++] = strdup("0");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* strInArray:
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
static int
|
|
|
|
strInArray(const char *pattern, char **arr, int arr_size)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < arr_size; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(pattern, arr[i]) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dumpSchema:
|
1997-09-07 07:04:48 +02:00
|
|
|
* we have a valid connection, we are now going to dump the schema
|
1996-07-09 08:22:35 +02:00
|
|
|
* into the file
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
TableInfo *
|
2000-07-04 16:25:28 +02:00
|
|
|
dumpSchema(Archive *fout,
|
|
|
|
int *numTablesPtr,
|
|
|
|
const char *tablename,
|
|
|
|
const bool aclsSkip,
|
|
|
|
const bool oids,
|
|
|
|
const bool schemaOnly,
|
|
|
|
const bool dataOnly)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int numTypes;
|
|
|
|
int numFuncs;
|
|
|
|
int numTables;
|
|
|
|
int numInherits;
|
|
|
|
int numAggregates;
|
|
|
|
int numOperators;
|
|
|
|
TypeInfo *tinfo = NULL;
|
|
|
|
FuncInfo *finfo = NULL;
|
|
|
|
AggInfo *agginfo = NULL;
|
|
|
|
TableInfo *tblinfo = NULL;
|
|
|
|
InhInfo *inhinfo = NULL;
|
|
|
|
OprInfo *oprinfo = NULL;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading user-defined types %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
tinfo = getTypes(&numTypes);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading user-defined functions %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
finfo = getFuncs(&numFuncs);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading user-defined aggregates %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
agginfo = getAggregates(&numAggregates);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading user-defined operators %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
oprinfo = getOperators(&numOperators);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading user-defined tables %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
1997-10-02 15:57:07 +02:00
|
|
|
tblinfo = getTables(&numTables, finfo, numFuncs);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading table inheritance information %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
inhinfo = getInherits(&numInherits);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s finding the attribute names and types for each table %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
getTableAttrs(tblinfo, numTables);
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s flagging inherited attributes in subtables %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
|
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (!tablename && !dataOnly)
|
2000-01-18 19:09:02 +01:00
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out database comment %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpDBComment(fout);
|
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
if (!tablename && fout)
|
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out user-defined types %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpTypes(fout, finfo, numFuncs, tinfo, numTypes);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out tables %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpTables(fout, tblinfo, numTables, inhinfo, numInherits,
|
|
|
|
tinfo, numTypes, tablename, aclsSkip, oids, schemaOnly, dataOnly);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (!tablename && !dataOnly)
|
1998-10-07 00:14:21 +02:00
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out user-defined procedural languages %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpProcLangs(fout, finfo, numFuncs, tinfo, numTypes);
|
|
|
|
}
|
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (!tablename && !dataOnly)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out user-defined functions %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpFuncs(fout, finfo, numFuncs, tinfo, numTypes);
|
|
|
|
}
|
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (!tablename && !dataOnly)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
|
|
|
if (g_verbose)
|
1998-10-07 00:14:21 +02:00
|
|
|
fprintf(stderr, "%s dumping out user-defined aggregates %s\n",
|
1997-09-07 07:04:48 +02:00
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes);
|
|
|
|
}
|
|
|
|
|
2000-07-04 16:25:28 +02:00
|
|
|
if (!tablename && !dataOnly)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out user-defined operators %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpOprs(fout, oprinfo, numOperators, tinfo, numTypes);
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
*numTablesPtr = numTables;
|
|
|
|
clearAggInfo(agginfo, numAggregates);
|
|
|
|
clearOprInfo(oprinfo, numOperators);
|
|
|
|
clearTypeInfo(tinfo, numTypes);
|
|
|
|
clearFuncInfo(finfo, numFuncs);
|
|
|
|
clearInhInfo(inhinfo, numInherits);
|
|
|
|
return tblinfo;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1996-08-24 22:49:41 +02:00
|
|
|
/*
|
|
|
|
* dumpSchemaIdx:
|
1997-09-07 07:04:48 +02:00
|
|
|
* dump indexes at the end for performance
|
1996-08-24 22:49:41 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern void
|
2000-07-04 16:25:28 +02:00
|
|
|
dumpSchemaIdx(Archive *fout, const char *tablename,
|
1997-09-08 23:56:23 +02:00
|
|
|
TableInfo *tblinfo, int numTables)
|
1996-08-24 22:49:41 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int numIndices;
|
|
|
|
IndInfo *indinfo;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s reading indices information %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
indinfo = getIndices(&numIndices);
|
|
|
|
|
|
|
|
if (fout)
|
|
|
|
{
|
|
|
|
if (g_verbose)
|
|
|
|
fprintf(stderr, "%s dumping out indices %s\n",
|
|
|
|
g_comment_start, g_comment_end);
|
|
|
|
dumpIndices(fout, indinfo, numIndices, tblinfo, numTables, tablename);
|
|
|
|
}
|
|
|
|
clearIndInfo(indinfo, numIndices);
|
1996-08-24 22:49:41 +02:00
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* flagInhAttrs -
|
1997-09-07 07:04:48 +02:00
|
|
|
* for each table in tblinfo, flag its inherited attributes
|
1996-07-09 08:22:35 +02:00
|
|
|
* so when we dump the table out, we don't dump out the inherited attributes
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* initializes the parentRels field of each table
|
|
|
|
*
|
|
|
|
* modifies tblinfo
|
|
|
|
*
|
|
|
|
*/
|
1997-08-19 23:40:56 +02:00
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
flagInhAttrs(TableInfo *tblinfo, int numTables,
|
|
|
|
InhInfo *inhinfo, int numInherits)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i,
|
|
|
|
j,
|
|
|
|
k;
|
|
|
|
int parentInd;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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--)
|
|
|
|
{
|
|
|
|
tblinfo[i].parentRels = findParentsByOid(tblinfo, numTables,
|
|
|
|
inhinfo, numInherits,
|
|
|
|
tblinfo[i].oid,
|
|
|
|
&tblinfo[i].numParents);
|
|
|
|
for (k = 0; k < tblinfo[i].numParents; k++)
|
|
|
|
{
|
|
|
|
parentInd = findTableByName(tblinfo, numTables,
|
|
|
|
tblinfo[i].parentRels[k]);
|
1998-09-20 05:18:43 +02:00
|
|
|
if (parentInd < 0)
|
|
|
|
{
|
|
|
|
/* shouldn't happen unless findParentsByOid is broken */
|
|
|
|
fprintf(stderr, "failed sanity check, table %s not found by flagInhAttrs\n",
|
|
|
|
tblinfo[i].parentRels[k]);
|
|
|
|
exit(2);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
for (j = 0; j < tblinfo[i].numatts; j++)
|
|
|
|
{
|
|
|
|
if (strInArray(tblinfo[i].attnames[j],
|
|
|
|
tblinfo[parentInd].attnames,
|
|
|
|
tblinfo[parentInd].numatts) != -1)
|
|
|
|
tblinfo[i].inhAttrs[j] = 1;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* findTableByName
|
1997-09-07 07:04:48 +02:00
|
|
|
* finds the index (in tblinfo) of the table with the given relname
|
|
|
|
* returns -1 if not found
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTE: should hash this, but just do linear search for now
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
1997-09-08 23:56:23 +02:00
|
|
|
findTableByName(TableInfo *tblinfo, int numTables, const char *relname)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < numTables; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(tblinfo[i].relname, relname) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* findTableByOid
|
1997-09-07 07:04:48 +02:00
|
|
|
* finds the index (in tblinfo) of the table with the given oid
|
|
|
|
* returns -1 if not found
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTE: should hash this, but just do linear search for now
|
|
|
|
*/
|
|
|
|
|
1997-08-19 23:40:56 +02:00
|
|
|
static int
|
1997-09-08 23:56:23 +02:00
|
|
|
findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < numTables; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(tblinfo[i].oid, oid) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* findFuncByName
|
1997-09-07 07:04:48 +02:00
|
|
|
* finds the index (in finfo) of the function with the given name
|
|
|
|
* returns -1 if not found
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTE: should hash this, but just do linear search for now
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
1997-09-08 23:56:23 +02:00
|
|
|
findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < numFuncs; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(finfo[i].proname, name) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-10-30 17:48:03 +01:00
|
|
|
/*
|
|
|
|
* fmtId
|
|
|
|
*
|
|
|
|
* checks input string for non-lowercase characters
|
|
|
|
* returns pointer to input string or string surrounded by double quotes
|
1998-10-02 18:43:41 +02:00
|
|
|
*
|
1999-05-25 18:15:34 +02:00
|
|
|
* Note that the returned string should be used immediately since it
|
|
|
|
* uses a static buffer to hold the string. Non-reentrant but faster?
|
1997-10-30 17:48:03 +01:00
|
|
|
*/
|
|
|
|
const char *
|
1998-12-14 00:41:32 +01:00
|
|
|
fmtId(const char *rawid, bool force_quotes)
|
1997-10-30 17:48:03 +01:00
|
|
|
{
|
2000-01-18 08:29:58 +01:00
|
|
|
static PQExpBuffer id_return = NULL;
|
1997-10-30 17:48:03 +01:00
|
|
|
const char *cp;
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-01-18 08:29:58 +01:00
|
|
|
if (!force_quotes)
|
|
|
|
{
|
2000-08-06 19:50:48 +02:00
|
|
|
/* do a quick check on the first character... */
|
2000-06-14 20:18:01 +02:00
|
|
|
if (!islower((int) *rawid))
|
2000-01-18 08:29:58 +01:00
|
|
|
force_quotes = true;
|
2000-08-06 19:50:48 +02:00
|
|
|
/* otherwise check the entire string */
|
2000-01-18 08:29:58 +01:00
|
|
|
else
|
|
|
|
for (cp = rawid; *cp; cp++)
|
|
|
|
{
|
2000-06-14 20:18:01 +02:00
|
|
|
if (!(islower((int) *cp) || isdigit((int) *cp) || (*cp == '_')))
|
2000-01-18 08:29:58 +01:00
|
|
|
{
|
|
|
|
force_quotes = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!force_quotes)
|
|
|
|
return rawid; /* no quoting needed */
|
1997-10-30 17:48:03 +01:00
|
|
|
|
1999-12-27 16:42:44 +01:00
|
|
|
if (id_return)
|
|
|
|
resetPQExpBuffer(id_return);
|
|
|
|
else
|
|
|
|
id_return = createPQExpBuffer();
|
1997-10-30 17:48:03 +01:00
|
|
|
|
2000-01-18 08:29:58 +01:00
|
|
|
appendPQExpBufferChar(id_return, '\"');
|
|
|
|
for (cp = rawid; *cp; cp++)
|
1998-02-26 05:46:47 +01:00
|
|
|
{
|
2000-08-06 19:50:48 +02:00
|
|
|
/* Did we find a double-quote in the string?
|
|
|
|
* Then make this a double double-quote per SQL99.
|
|
|
|
* Before, we put in a backslash/double-quote pair.
|
|
|
|
* - thomas 2000-08-05 */
|
2000-01-18 08:29:58 +01:00
|
|
|
if (*cp == '\"')
|
2000-08-06 19:50:48 +02:00
|
|
|
{
|
|
|
|
appendPQExpBufferChar(id_return, '\"');
|
|
|
|
appendPQExpBufferChar(id_return, '\"');
|
|
|
|
}
|
2000-01-18 08:29:58 +01:00
|
|
|
appendPQExpBufferChar(id_return, *cp);
|
1998-02-26 05:46:47 +01:00
|
|
|
}
|
2000-01-18 08:29:58 +01:00
|
|
|
appendPQExpBufferChar(id_return, '\"');
|
1999-12-27 16:42:44 +01:00
|
|
|
|
2000-01-18 08:29:58 +01:00
|
|
|
return id_return->data;
|
1998-02-26 05:46:47 +01:00
|
|
|
} /* fmtId() */
|