mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-17 20:03:23 +02:00
413 lines
9.6 KiB
C
413 lines
9.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* common.c--
|
|
* common routines between pg_dump and pg4_dump
|
|
*
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.8 1996/11/26 03:19:40 bryanh 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.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */
|
|
#ifdef sparc_solaris
|
|
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
|
|
#endif
|
|
|
|
#include "postgres.h"
|
|
#include "libpq-fe.h"
|
|
#include <port-protos.h> /* for strdup() */
|
|
|
|
#include "pg_dump.h"
|
|
|
|
/*
|
|
* findTypeByOid
|
|
* given an oid of a type, return its typename
|
|
*
|
|
* if oid is "0", return "opaque" -- this is a special case
|
|
*
|
|
* NOTE: should hash this, but just do linear search for now
|
|
*/
|
|
|
|
char*
|
|
findTypeByOid(TypeInfo* tinfo, int numTypes, const char* oid)
|
|
{
|
|
int i;
|
|
|
|
if (strcmp(oid, "0") == 0) return g_opaque_type;
|
|
|
|
for (i=0;i<numTypes;i++) {
|
|
if (strcmp(tinfo[i].oid, oid) == 0)
|
|
return tinfo[i].typname;
|
|
}
|
|
|
|
/* should never get here */
|
|
fprintf(stderr,"failed sanity check, type with oid %s was not found\n",
|
|
oid);
|
|
exit(2);
|
|
}
|
|
|
|
/*
|
|
* 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 */
|
|
fprintf(stderr,"failed sanity check, opr with oid %s was not found\n",
|
|
oid);
|
|
exit(2);
|
|
}
|
|
|
|
|
|
/*
|
|
* findParentsByOid --
|
|
* given the oid of a class, return the names of its parent classes
|
|
* and assign the number of parents to the last argument.
|
|
*
|
|
*
|
|
* returns NULL if none
|
|
*/
|
|
|
|
char**
|
|
findParentsByOid(TableInfo* tblinfo, int numTables,
|
|
InhInfo* inhinfo, int numInherits, const char *oid,
|
|
int *numParentsPtr)
|
|
{
|
|
int i,j;
|
|
int parentInd;
|
|
char** result;
|
|
int numParents;
|
|
|
|
numParents = 0;
|
|
for (i=0;i<numInherits;i++) {
|
|
if ( strcmp(inhinfo[i].inhrel, oid) == 0) {
|
|
numParents++;
|
|
}
|
|
}
|
|
|
|
*numParentsPtr = numParents;
|
|
|
|
if (numParents > 0) {
|
|
result = (char**)malloc(sizeof(char*) * numParents);
|
|
j = 0;
|
|
for (i=0;i<numInherits;i++) {
|
|
if ( strcmp(inhinfo[i].inhrel, oid) == 0) {
|
|
parentInd = findTableByOid(tblinfo, numTables,
|
|
inhinfo[i].inhparent);
|
|
result[j++] = tblinfo[parentInd].relname;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* parseArgTypes
|
|
* parse a string of eight numbers delimited by spaces
|
|
* into a character array
|
|
*/
|
|
|
|
void
|
|
parseArgTypes(char **argtypes, const char* str)
|
|
{
|
|
int j, argNum;
|
|
char temp[100];
|
|
char s;
|
|
|
|
argNum = 0;
|
|
j = 0;
|
|
while ( (s = *str) != '\0') {
|
|
if (s == ' ') {
|
|
temp[j] = '\0';
|
|
argtypes[argNum] = strdup(temp);
|
|
argNum++;
|
|
j = 0;
|
|
} else {
|
|
temp[j] = s;
|
|
j++;
|
|
}
|
|
str++;
|
|
}
|
|
if (j != 0) {
|
|
temp[j] = '\0';
|
|
argtypes[argNum] = strdup(temp);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* 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
|
|
*
|
|
*/
|
|
|
|
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(FILE *fout, int *numTablesPtr, const char *tablename)
|
|
{
|
|
int numTypes;
|
|
int numFuncs;
|
|
int numTables;
|
|
int numInherits;
|
|
int numAggregates;
|
|
int numOperators;
|
|
TypeInfo *tinfo;
|
|
FuncInfo *finfo;
|
|
AggInfo *agginfo;
|
|
TableInfo *tblinfo;
|
|
InhInfo *inhinfo;
|
|
OprInfo *oprinfo;
|
|
|
|
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);
|
|
tblinfo = getTables(&numTables);
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
|
|
if (fout) {
|
|
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);
|
|
}
|
|
|
|
if (!tablename && fout) {
|
|
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);
|
|
}
|
|
|
|
if (!tablename && fout) {
|
|
if (g_verbose) fprintf(stderr,"%s dumping out user-defined functions %s\n",
|
|
g_comment_start, g_comment_end);
|
|
dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes);
|
|
}
|
|
|
|
if (!tablename && fout) {
|
|
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);
|
|
}
|
|
|
|
*numTablesPtr = numTables;
|
|
return tblinfo;
|
|
}
|
|
|
|
|
|
/*
|
|
* dumpSchemaIdx:
|
|
* dump indexes at the end for performance
|
|
*
|
|
*/
|
|
|
|
extern void
|
|
dumpSchemaIdx(FILE *fout, int *numTablesPtr, const char *tablename,
|
|
TableInfo* tblinfo, int numTables)
|
|
{
|
|
int numIndices;
|
|
IndInfo *indinfo;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/* 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
|
|
*
|
|
*/
|
|
void
|
|
flagInhAttrs(TableInfo* tblinfo, int numTables,
|
|
InhInfo* inhinfo, int numInherits)
|
|
{
|
|
int i,j,k;
|
|
int parentInd;
|
|
|
|
/* 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]);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* isArchiveName
|
|
*
|
|
* returns true if the relation name is an archive name, false otherwise
|
|
*/
|
|
int
|
|
isArchiveName(const char* relname)
|
|
{
|
|
return (strlen(relname) > 1 && relname[1] == ',');
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|