1 /*-------------------------------------------------------------------------
4 * common routines between pg_dump and pg4_dump
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.38 2000/01/18 07:29:58 tgl Exp $
12 * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
14 * - Fixed dumpTable output to output lengths for char and varchar types!
15 * - Added single. quote to twin single quote expansion for 'insert' string
18 *-------------------------------------------------------------------------
33 static char **findParentsByOid(TableInfo *tbinfo, int numTables,
34 InhInfo *inhinfo, int numInherits,
37 static int findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
38 static void flagInhAttrs(TableInfo *tbinfo, int numTables,
39 InhInfo *inhinfo, int numInherits);
40 static int strInArray(const char *pattern, char **arr, int arr_size);
44 * given an oid of a type, return its typename
46 * if oid is "0", return "opaque" -- this is a special case
48 * NOTE: should hash this, but just do linear search for now
52 findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid)
56 if (strcmp(oid, "0") == 0)
59 for (i = 0; i < numTypes; i++)
61 if (strcmp(tinfo[i].oid, oid) == 0)
62 return tinfo[i].typname;
65 /* should never get here */
66 fprintf(stderr, "failed sanity check, type with oid %s was not found\n",
73 * given the oid of an operator, return the name of the operator
76 * NOTE: should hash this, but just do linear search for now
80 findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
84 for (i = 0; i < numOprs; i++)
86 if (strcmp(oprinfo[i].oid, oid) == 0)
87 return oprinfo[i].oprname;
90 /* should never get here */
91 fprintf(stderr, "failed sanity check, opr with oid %s was not found\n",
99 * given the oid of a class, return the names of its parent classes
100 * and assign the number of parents to the last argument.
103 * returns NULL if none
107 findParentsByOid(TableInfo *tblinfo, int numTables,
108 InhInfo *inhinfo, int numInherits, const char *oid,
119 for (i = 0; i < numInherits; i++)
121 if (strcmp(inhinfo[i].inhrelid, oid) == 0)
125 *numParentsPtr = numParents;
129 result = (char **) malloc(sizeof(char *) * numParents);
131 for (i = 0; i < numInherits; i++)
133 if (strcmp(inhinfo[i].inhrelid, oid) == 0)
135 parentInd = findTableByOid(tblinfo, numTables,
136 inhinfo[i].inhparent);
139 selfInd = findTableByOid(tblinfo, numTables, oid);
141 "failed sanity check, parent oid %s of table %s (oid %s) was not found\n",
142 inhinfo[i].inhparent,
143 (selfInd >= 0) ? tblinfo[selfInd].relname : "",
147 result[j++] = tblinfo[parentInd].relname;
158 * parse a string of numbers delimited by spaces into a character array
162 parseNumericArray(const char *str, char **array, int arraysize)
174 if (s == ' ' || s == '\0')
178 if (argNum >= arraysize)
180 fprintf(stderr, "parseNumericArray: too many numbers\n");
184 array[argNum++] = strdup(temp);
192 if (!isdigit(s) || j >= sizeof(temp)-1)
194 fprintf(stderr, "parseNumericArray: bogus number\n");
200 while (argNum < arraysize)
201 array[argNum++] = strdup("0");
207 * takes in a string and a string array and the number of elements in the
209 * returns the index if the string is somewhere in the array, -1 otherwise
214 strInArray(const char *pattern, char **arr, int arr_size)
218 for (i = 0; i < arr_size; i++)
220 if (strcmp(pattern, arr[i]) == 0)
228 * we have a valid connection, we are now going to dump the schema
234 dumpSchema(FILE *fout,
236 const char *tablename,
245 TypeInfo *tinfo = NULL;
246 FuncInfo *finfo = NULL;
247 AggInfo *agginfo = NULL;
248 TableInfo *tblinfo = NULL;
249 InhInfo *inhinfo = NULL;
250 OprInfo *oprinfo = NULL;
253 fprintf(stderr, "%s reading user-defined types %s\n",
254 g_comment_start, g_comment_end);
255 tinfo = getTypes(&numTypes);
258 fprintf(stderr, "%s reading user-defined functions %s\n",
259 g_comment_start, g_comment_end);
260 finfo = getFuncs(&numFuncs);
263 fprintf(stderr, "%s reading user-defined aggregates %s\n",
264 g_comment_start, g_comment_end);
265 agginfo = getAggregates(&numAggregates);
268 fprintf(stderr, "%s reading user-defined operators %s\n",
269 g_comment_start, g_comment_end);
270 oprinfo = getOperators(&numOperators);
273 fprintf(stderr, "%s reading user-defined tables %s\n",
274 g_comment_start, g_comment_end);
275 tblinfo = getTables(&numTables, finfo, numFuncs);
278 fprintf(stderr, "%s reading table inheritance information %s\n",
279 g_comment_start, g_comment_end);
280 inhinfo = getInherits(&numInherits);
283 fprintf(stderr, "%s finding the attribute names and types for each table %s\n",
284 g_comment_start, g_comment_end);
285 getTableAttrs(tblinfo, numTables);
288 fprintf(stderr, "%s flagging inherited attributes in subtables %s\n",
289 g_comment_start, g_comment_end);
290 flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
292 if (!tablename && fout)
295 fprintf(stderr, "%s dumping out user-defined types %s\n",
296 g_comment_start, g_comment_end);
297 dumpTypes(fout, finfo, numFuncs, tinfo, numTypes);
303 fprintf(stderr, "%s dumping out tables %s\n",
304 g_comment_start, g_comment_end);
305 dumpTables(fout, tblinfo, numTables, inhinfo, numInherits,
306 tinfo, numTypes, tablename, aclsSkip);
309 if (!tablename && fout)
312 fprintf(stderr, "%s dumping out user-defined procedural languages %s\n",
313 g_comment_start, g_comment_end);
314 dumpProcLangs(fout, finfo, numFuncs, tinfo, numTypes);
317 if (!tablename && fout)
320 fprintf(stderr, "%s dumping out user-defined functions %s\n",
321 g_comment_start, g_comment_end);
322 dumpFuncs(fout, finfo, numFuncs, tinfo, numTypes);
325 if (!tablename && fout)
328 fprintf(stderr, "%s dumping out user-defined aggregates %s\n",
329 g_comment_start, g_comment_end);
330 dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes);
333 if (!tablename && fout)
336 fprintf(stderr, "%s dumping out user-defined operators %s\n",
337 g_comment_start, g_comment_end);
338 dumpOprs(fout, oprinfo, numOperators, tinfo, numTypes);
341 *numTablesPtr = numTables;
342 clearAggInfo(agginfo, numAggregates);
343 clearOprInfo(oprinfo, numOperators);
344 clearTypeInfo(tinfo, numTypes);
345 clearFuncInfo(finfo, numFuncs);
346 clearInhInfo(inhinfo, numInherits);
352 * dump indexes at the end for performance
357 dumpSchemaIdx(FILE *fout, const char *tablename,
358 TableInfo *tblinfo, int numTables)
364 fprintf(stderr, "%s reading indices information %s\n",
365 g_comment_start, g_comment_end);
366 indinfo = getIndices(&numIndices);
371 fprintf(stderr, "%s dumping out indices %s\n",
372 g_comment_start, g_comment_end);
373 dumpIndices(fout, indinfo, numIndices, tblinfo, numTables, tablename);
375 clearIndInfo(indinfo, numIndices);
379 * for each table in tblinfo, flag its inherited attributes
380 * so when we dump the table out, we don't dump out the inherited attributes
382 * initializes the parentRels field of each table
388 flagInhAttrs(TableInfo *tblinfo, int numTables,
389 InhInfo *inhinfo, int numInherits)
397 * we go backwards because the tables in tblinfo are in OID order,
398 * meaning the subtables are after the parent tables we flag inherited
399 * attributes from child tables first
401 for (i = numTables - 1; i >= 0; i--)
403 tblinfo[i].parentRels = findParentsByOid(tblinfo, numTables,
404 inhinfo, numInherits,
406 &tblinfo[i].numParents);
407 for (k = 0; k < tblinfo[i].numParents; k++)
409 parentInd = findTableByName(tblinfo, numTables,
410 tblinfo[i].parentRels[k]);
413 /* shouldn't happen unless findParentsByOid is broken */
414 fprintf(stderr, "failed sanity check, table %s not found by flagInhAttrs\n",
415 tblinfo[i].parentRels[k]);
418 for (j = 0; j < tblinfo[i].numatts; j++)
420 if (strInArray(tblinfo[i].attnames[j],
421 tblinfo[parentInd].attnames,
422 tblinfo[parentInd].numatts) != -1)
423 tblinfo[i].inhAttrs[j] = 1;
432 * finds the index (in tblinfo) of the table with the given relname
433 * returns -1 if not found
435 * NOTE: should hash this, but just do linear search for now
439 findTableByName(TableInfo *tblinfo, int numTables, const char *relname)
443 for (i = 0; i < numTables; i++)
445 if (strcmp(tblinfo[i].relname, relname) == 0)
453 * finds the index (in tblinfo) of the table with the given oid
454 * returns -1 if not found
456 * NOTE: should hash this, but just do linear search for now
460 findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
464 for (i = 0; i < numTables; i++)
466 if (strcmp(tblinfo[i].oid, oid) == 0)
475 * finds the index (in finfo) of the function with the given name
476 * returns -1 if not found
478 * NOTE: should hash this, but just do linear search for now
482 findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
486 for (i = 0; i < numFuncs; i++)
488 if (strcmp(finfo[i].proname, name) == 0)
497 * checks input string for non-lowercase characters
498 * returns pointer to input string or string surrounded by double quotes
500 * Note that the returned string should be used immediately since it
501 * uses a static buffer to hold the string. Non-reentrant but faster?
504 fmtId(const char *rawid, bool force_quotes)
506 static PQExpBuffer id_return = NULL;
511 if (! islower(*rawid))
514 for (cp = rawid; *cp; cp++)
516 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_')))
525 return rawid; /* no quoting needed */
528 resetPQExpBuffer(id_return);
530 id_return = createPQExpBuffer();
532 appendPQExpBufferChar(id_return, '\"');
533 for (cp = rawid; *cp; cp++)
536 appendPQExpBufferChar(id_return, '\\');
537 appendPQExpBufferChar(id_return, *cp);
539 appendPQExpBufferChar(id_return, '\"');
541 return id_return->data;