Disallow empty passwords in LDAP authentication, the same way
[PostgreSQL.git] / src / bin / pg_dump / common.c
blob2d43e80fcd544e8deaa9f22751ad32f8e455abd2
1 /*-------------------------------------------------------------------------
3 * common.c
4 * common routines between pg_dump and pg4_dump
6 * Since pg4_dump is long-dead code, there is no longer any useful distinction
7 * between this file and pg_dump.c.
9 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
13 * IDENTIFICATION
14 * $PostgreSQL$
16 *-------------------------------------------------------------------------
18 #include "postgres_fe.h"
20 #include <ctype.h>
22 #include "catalog/pg_class.h"
24 #include "pg_backup_archiver.h"
28 * Variables for mapping DumpId to DumpableObject
30 static DumpableObject **dumpIdMap = NULL;
31 static int allocedDumpIds = 0;
32 static DumpId lastDumpId = 0;
35 * Variables for mapping CatalogId to DumpableObject
37 static bool catalogIdMapValid = false;
38 static DumpableObject **catalogIdMap = NULL;
39 static int numCatalogIds = 0;
42 * These variables are static to avoid the notational cruft of having to pass
43 * them into findTableByOid() and friends. For each of these arrays, we
44 * build a sorted-by-OID index array immediately after it's built, and then
45 * we use binary search in findTableByOid() and friends. (qsort'ing the base
46 * arrays themselves would be simpler, but it doesn't work because pg_dump.c
47 * may have already established pointers between items.)
49 static TableInfo *tblinfo;
50 static TypeInfo *typinfo;
51 static FuncInfo *funinfo;
52 static OprInfo *oprinfo;
53 static int numTables;
54 static int numTypes;
55 static int numFuncs;
56 static int numOperators;
57 static DumpableObject **tblinfoindex;
58 static DumpableObject **typinfoindex;
59 static DumpableObject **funinfoindex;
60 static DumpableObject **oprinfoindex;
63 static void flagInhTables(TableInfo *tbinfo, int numTables,
64 InhInfo *inhinfo, int numInherits);
65 static void flagInhAttrs(TableInfo *tblinfo, int numTables);
66 static DumpableObject **buildIndexArray(void *objArray, int numObjs,
67 Size objSize);
68 static int DOCatalogIdCompare(const void *p1, const void *p2);
69 static void findParentsByOid(TableInfo *self,
70 InhInfo *inhinfo, int numInherits);
71 static int strInArray(const char *pattern, char **arr, int arr_size);
75 * getSchemaData
76 * Collect information about all potentially dumpable objects
78 TableInfo *
79 getSchemaData(int *numTablesPtr)
81 NamespaceInfo *nsinfo;
82 AggInfo *agginfo;
83 InhInfo *inhinfo;
84 RuleInfo *ruleinfo;
85 ProcLangInfo *proclanginfo;
86 CastInfo *castinfo;
87 OpclassInfo *opcinfo;
88 OpfamilyInfo *opfinfo;
89 ConvInfo *convinfo;
90 TSParserInfo *prsinfo;
91 TSTemplateInfo *tmplinfo;
92 TSDictInfo *dictinfo;
93 TSConfigInfo *cfginfo;
94 FdwInfo *fdwinfo;
95 ForeignServerInfo *srvinfo;
96 int numNamespaces;
97 int numAggregates;
98 int numInherits;
99 int numRules;
100 int numProcLangs;
101 int numCasts;
102 int numOpclasses;
103 int numOpfamilies;
104 int numConversions;
105 int numTSParsers;
106 int numTSTemplates;
107 int numTSDicts;
108 int numTSConfigs;
109 int numForeignDataWrappers;
110 int numForeignServers;
112 if (g_verbose)
113 write_msg(NULL, "reading schemas\n");
114 nsinfo = getNamespaces(&numNamespaces);
116 if (g_verbose)
117 write_msg(NULL, "reading user-defined functions\n");
118 funinfo = getFuncs(&numFuncs);
119 funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
121 /* this must be after getFuncs */
122 if (g_verbose)
123 write_msg(NULL, "reading user-defined types\n");
124 typinfo = getTypes(&numTypes);
125 typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
127 /* this must be after getFuncs, too */
128 if (g_verbose)
129 write_msg(NULL, "reading procedural languages\n");
130 proclanginfo = getProcLangs(&numProcLangs);
132 if (g_verbose)
133 write_msg(NULL, "reading user-defined aggregate functions\n");
134 agginfo = getAggregates(&numAggregates);
136 if (g_verbose)
137 write_msg(NULL, "reading user-defined operators\n");
138 oprinfo = getOperators(&numOperators);
139 oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
141 if (g_verbose)
142 write_msg(NULL, "reading user-defined operator classes\n");
143 opcinfo = getOpclasses(&numOpclasses);
145 if (g_verbose)
146 write_msg(NULL, "reading user-defined text search parsers\n");
147 prsinfo = getTSParsers(&numTSParsers);
149 if (g_verbose)
150 write_msg(NULL, "reading user-defined text search templates\n");
151 tmplinfo = getTSTemplates(&numTSTemplates);
153 if (g_verbose)
154 write_msg(NULL, "reading user-defined text search dictionaries\n");
155 dictinfo = getTSDictionaries(&numTSDicts);
157 if (g_verbose)
158 write_msg(NULL, "reading user-defined text search configurations\n");
159 cfginfo = getTSConfigurations(&numTSConfigs);
161 if (g_verbose)
162 write_msg(NULL, "reading user-defined foreign-data wrappers\n");
163 fdwinfo = getForeignDataWrappers(&numForeignDataWrappers);
165 if (g_verbose)
166 write_msg(NULL, "reading user-defined foreign servers\n");
167 srvinfo = getForeignServers(&numForeignServers);
169 if (g_verbose)
170 write_msg(NULL, "reading user-defined operator families\n");
171 opfinfo = getOpfamilies(&numOpfamilies);
173 if (g_verbose)
174 write_msg(NULL, "reading user-defined conversions\n");
175 convinfo = getConversions(&numConversions);
177 if (g_verbose)
178 write_msg(NULL, "reading user-defined tables\n");
179 tblinfo = getTables(&numTables);
180 tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
182 if (g_verbose)
183 write_msg(NULL, "reading table inheritance information\n");
184 inhinfo = getInherits(&numInherits);
186 if (g_verbose)
187 write_msg(NULL, "reading rewrite rules\n");
188 ruleinfo = getRules(&numRules);
190 if (g_verbose)
191 write_msg(NULL, "reading type casts\n");
192 castinfo = getCasts(&numCasts);
194 /* Link tables to parents, mark parents of target tables interesting */
195 if (g_verbose)
196 write_msg(NULL, "finding inheritance relationships\n");
197 flagInhTables(tblinfo, numTables, inhinfo, numInherits);
199 if (g_verbose)
200 write_msg(NULL, "reading column info for interesting tables\n");
201 getTableAttrs(tblinfo, numTables);
203 if (g_verbose)
204 write_msg(NULL, "flagging inherited columns in subtables\n");
205 flagInhAttrs(tblinfo, numTables);
207 if (g_verbose)
208 write_msg(NULL, "reading indexes\n");
209 getIndexes(tblinfo, numTables);
211 if (g_verbose)
212 write_msg(NULL, "reading constraints\n");
213 getConstraints(tblinfo, numTables);
215 if (g_verbose)
216 write_msg(NULL, "reading triggers\n");
217 getTriggers(tblinfo, numTables);
219 *numTablesPtr = numTables;
220 return tblinfo;
223 /* flagInhTables -
224 * Fill in parent link fields of every target table, and mark
225 * parents of target tables as interesting
227 * Note that only direct ancestors of targets are marked interesting.
228 * This is sufficient; we don't much care whether they inherited their
229 * attributes or not.
231 * modifies tblinfo
233 static void
234 flagInhTables(TableInfo *tblinfo, int numTables,
235 InhInfo *inhinfo, int numInherits)
237 int i,
239 int numParents;
240 TableInfo **parents;
242 for (i = 0; i < numTables; i++)
244 /* Sequences and views never have parents */
245 if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
246 tblinfo[i].relkind == RELKIND_VIEW)
247 continue;
249 /* Don't bother computing anything for non-target tables, either */
250 if (!tblinfo[i].dobj.dump)
251 continue;
253 /* Find all the immediate parent tables */
254 findParentsByOid(&tblinfo[i], inhinfo, numInherits);
256 /* Mark the parents as interesting for getTableAttrs */
257 numParents = tblinfo[i].numParents;
258 parents = tblinfo[i].parents;
259 for (j = 0; j < numParents; j++)
260 parents[j]->interesting = true;
264 /* flagInhAttrs -
265 * for each dumpable table in tblinfo, flag its inherited attributes
266 * so when we dump the table out, we don't dump out the inherited attributes
268 * modifies tblinfo
270 static void
271 flagInhAttrs(TableInfo *tblinfo, int numTables)
273 int i,
277 for (i = 0; i < numTables; i++)
279 TableInfo *tbinfo = &(tblinfo[i]);
280 int numParents;
281 TableInfo **parents;
282 TableInfo *parent;
284 /* Sequences and views never have parents */
285 if (tbinfo->relkind == RELKIND_SEQUENCE ||
286 tbinfo->relkind == RELKIND_VIEW)
287 continue;
289 /* Don't bother computing anything for non-target tables, either */
290 if (!tbinfo->dobj.dump)
291 continue;
293 numParents = tbinfo->numParents;
294 parents = tbinfo->parents;
296 if (numParents == 0)
297 continue; /* nothing to see here, move along */
299 /*----------------------------------------------------------------
300 * For each attr, check the parent info: if no parent has an attr
301 * with the same name, then it's not inherited. If there *is* an
302 * attr with the same name, then only dump it if:
304 * - it is NOT NULL and zero parents are NOT NULL
305 * OR
306 * - it has a default value AND the default value does not match
307 * all parent default values, or no parents specify a default.
309 * See discussion on -hackers around 2-Apr-2001.
310 *----------------------------------------------------------------
312 for (j = 0; j < tbinfo->numatts; j++)
314 bool foundAttr; /* Attr was found in a parent */
315 bool foundNotNull; /* Attr was NOT NULL in a parent */
316 bool defaultsMatch; /* All non-empty defaults match */
317 bool defaultsFound; /* Found a default in a parent */
318 AttrDefInfo *attrDef;
320 foundAttr = false;
321 foundNotNull = false;
322 defaultsMatch = true;
323 defaultsFound = false;
325 attrDef = tbinfo->attrdefs[j];
327 for (k = 0; k < numParents; k++)
329 int inhAttrInd;
331 parent = parents[k];
332 inhAttrInd = strInArray(tbinfo->attnames[j],
333 parent->attnames,
334 parent->numatts);
336 if (inhAttrInd != -1)
338 AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
340 foundAttr = true;
341 foundNotNull |= parent->notnull[inhAttrInd];
342 if (inhDef != NULL)
344 defaultsFound = true;
347 * If any parent has a default and the child doesn't,
348 * we have to emit an explicit DEFAULT NULL clause for
349 * the child, else the parent's default will win.
351 if (attrDef == NULL)
353 attrDef = (AttrDefInfo *) malloc(sizeof(AttrDefInfo));
354 attrDef->dobj.objType = DO_ATTRDEF;
355 attrDef->dobj.catId.tableoid = 0;
356 attrDef->dobj.catId.oid = 0;
357 AssignDumpId(&attrDef->dobj);
358 attrDef->adtable = tbinfo;
359 attrDef->adnum = j + 1;
360 attrDef->adef_expr = strdup("NULL");
362 attrDef->dobj.name = strdup(tbinfo->dobj.name);
363 attrDef->dobj.namespace = tbinfo->dobj.namespace;
365 attrDef->dobj.dump = tbinfo->dobj.dump;
367 attrDef->separate = false;
368 addObjectDependency(&tbinfo->dobj,
369 attrDef->dobj.dumpId);
371 tbinfo->attrdefs[j] = attrDef;
373 if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
375 defaultsMatch = false;
378 * Whenever there is a non-matching parent
379 * default, add a dependency to force the parent
380 * default to be dumped first, in case the
381 * defaults end up being dumped as separate
382 * commands. Otherwise the parent default will
383 * override the child's when it is applied.
385 addObjectDependency(&attrDef->dobj,
386 inhDef->dobj.dumpId);
393 * Based on the scan of the parents, decide if we can rely on the
394 * inherited attr
396 if (foundAttr) /* Attr was inherited */
398 /* Set inherited flag by default */
399 tbinfo->inhAttrs[j] = true;
400 tbinfo->inhAttrDef[j] = true;
401 tbinfo->inhNotNull[j] = true;
404 * Clear it if attr had a default, but parents did not, or
405 * mismatch
407 if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
409 tbinfo->inhAttrs[j] = false;
410 tbinfo->inhAttrDef[j] = false;
414 * Clear it if NOT NULL and none of the parents were NOT NULL
416 if (tbinfo->notnull[j] && !foundNotNull)
418 tbinfo->inhAttrs[j] = false;
419 tbinfo->inhNotNull[j] = false;
422 /* Clear it if attr has local definition */
423 if (tbinfo->attislocal[j])
424 tbinfo->inhAttrs[j] = false;
431 * AssignDumpId
432 * Given a newly-created dumpable object, assign a dump ID,
433 * and enter the object into the lookup table.
435 * The caller is expected to have filled in objType and catId,
436 * but not any of the other standard fields of a DumpableObject.
438 void
439 AssignDumpId(DumpableObject *dobj)
441 dobj->dumpId = ++lastDumpId;
442 dobj->name = NULL; /* must be set later */
443 dobj->namespace = NULL; /* may be set later */
444 dobj->dump = true; /* default assumption */
445 dobj->dependencies = NULL;
446 dobj->nDeps = 0;
447 dobj->allocDeps = 0;
449 while (dobj->dumpId >= allocedDumpIds)
451 int newAlloc;
453 if (allocedDumpIds <= 0)
455 newAlloc = 256;
456 dumpIdMap = (DumpableObject **)
457 pg_malloc(newAlloc * sizeof(DumpableObject *));
459 else
461 newAlloc = allocedDumpIds * 2;
462 dumpIdMap = (DumpableObject **)
463 pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
465 memset(dumpIdMap + allocedDumpIds, 0,
466 (newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
467 allocedDumpIds = newAlloc;
469 dumpIdMap[dobj->dumpId] = dobj;
471 /* mark catalogIdMap invalid, but don't rebuild it yet */
472 catalogIdMapValid = false;
476 * Assign a DumpId that's not tied to a DumpableObject.
478 * This is used when creating a "fixed" ArchiveEntry that doesn't need to
479 * participate in the sorting logic.
481 DumpId
482 createDumpId(void)
484 return ++lastDumpId;
488 * Return the largest DumpId so far assigned
490 DumpId
491 getMaxDumpId(void)
493 return lastDumpId;
497 * Find a DumpableObject by dump ID
499 * Returns NULL for invalid ID
501 DumpableObject *
502 findObjectByDumpId(DumpId dumpId)
504 if (dumpId <= 0 || dumpId >= allocedDumpIds)
505 return NULL; /* out of range? */
506 return dumpIdMap[dumpId];
510 * Find a DumpableObject by catalog ID
512 * Returns NULL for unknown ID
514 * We use binary search in a sorted list that is built on first call.
515 * If AssignDumpId() and findObjectByCatalogId() calls were intermixed,
516 * the code would work, but possibly be very slow. In the current usage
517 * pattern that does not happen, indeed we only need to build the list once.
519 DumpableObject *
520 findObjectByCatalogId(CatalogId catalogId)
522 DumpableObject **low;
523 DumpableObject **high;
525 if (!catalogIdMapValid)
527 if (catalogIdMap)
528 free(catalogIdMap);
529 getDumpableObjects(&catalogIdMap, &numCatalogIds);
530 if (numCatalogIds > 1)
531 qsort((void *) catalogIdMap, numCatalogIds,
532 sizeof(DumpableObject *), DOCatalogIdCompare);
533 catalogIdMapValid = true;
537 * We could use bsearch() here, but the notational cruft of calling
538 * bsearch is nearly as bad as doing it ourselves; and the generalized
539 * bsearch function is noticeably slower as well.
541 if (numCatalogIds <= 0)
542 return NULL;
543 low = catalogIdMap;
544 high = catalogIdMap + (numCatalogIds - 1);
545 while (low <= high)
547 DumpableObject **middle;
548 int difference;
550 middle = low + (high - low) / 2;
551 /* comparison must match DOCatalogIdCompare, below */
552 difference = oidcmp((*middle)->catId.oid, catalogId.oid);
553 if (difference == 0)
554 difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
555 if (difference == 0)
556 return *middle;
557 else if (difference < 0)
558 low = middle + 1;
559 else
560 high = middle - 1;
562 return NULL;
566 * Find a DumpableObject by OID, in a pre-sorted array of one type of object
568 * Returns NULL for unknown OID
570 static DumpableObject *
571 findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
573 DumpableObject **low;
574 DumpableObject **high;
577 * This is the same as findObjectByCatalogId except we assume we need not
578 * look at table OID because the objects are all the same type.
580 * We could use bsearch() here, but the notational cruft of calling
581 * bsearch is nearly as bad as doing it ourselves; and the generalized
582 * bsearch function is noticeably slower as well.
584 if (numObjs <= 0)
585 return NULL;
586 low = indexArray;
587 high = indexArray + (numObjs - 1);
588 while (low <= high)
590 DumpableObject **middle;
591 int difference;
593 middle = low + (high - low) / 2;
594 difference = oidcmp((*middle)->catId.oid, oid);
595 if (difference == 0)
596 return *middle;
597 else if (difference < 0)
598 low = middle + 1;
599 else
600 high = middle - 1;
602 return NULL;
606 * Build an index array of DumpableObject pointers, sorted by OID
608 static DumpableObject **
609 buildIndexArray(void *objArray, int numObjs, Size objSize)
611 DumpableObject **ptrs;
612 int i;
614 ptrs = (DumpableObject **) malloc(numObjs * sizeof(DumpableObject *));
615 for (i = 0; i < numObjs; i++)
616 ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
618 /* We can use DOCatalogIdCompare to sort since its first key is OID */
619 if (numObjs > 1)
620 qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
621 DOCatalogIdCompare);
623 return ptrs;
627 * qsort comparator for pointers to DumpableObjects
629 static int
630 DOCatalogIdCompare(const void *p1, const void *p2)
632 DumpableObject *obj1 = *(DumpableObject **) p1;
633 DumpableObject *obj2 = *(DumpableObject **) p2;
634 int cmpval;
637 * Compare OID first since it's usually unique, whereas there will only be
638 * a few distinct values of tableoid.
640 cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
641 if (cmpval == 0)
642 cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
643 return cmpval;
647 * Build an array of pointers to all known dumpable objects
649 * This simply creates a modifiable copy of the internal map.
651 void
652 getDumpableObjects(DumpableObject ***objs, int *numObjs)
654 int i,
657 *objs = (DumpableObject **)
658 pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
659 j = 0;
660 for (i = 1; i < allocedDumpIds; i++)
662 if (dumpIdMap[i])
663 (*objs)[j++] = dumpIdMap[i];
665 *numObjs = j;
669 * Add a dependency link to a DumpableObject
671 * Note: duplicate dependencies are currently not eliminated
673 void
674 addObjectDependency(DumpableObject *dobj, DumpId refId)
676 if (dobj->nDeps >= dobj->allocDeps)
678 if (dobj->allocDeps <= 0)
680 dobj->allocDeps = 16;
681 dobj->dependencies = (DumpId *)
682 pg_malloc(dobj->allocDeps * sizeof(DumpId));
684 else
686 dobj->allocDeps *= 2;
687 dobj->dependencies = (DumpId *)
688 pg_realloc(dobj->dependencies,
689 dobj->allocDeps * sizeof(DumpId));
692 dobj->dependencies[dobj->nDeps++] = refId;
696 * Remove a dependency link from a DumpableObject
698 * If there are multiple links, all are removed
700 void
701 removeObjectDependency(DumpableObject *dobj, DumpId refId)
703 int i;
704 int j = 0;
706 for (i = 0; i < dobj->nDeps; i++)
708 if (dobj->dependencies[i] != refId)
709 dobj->dependencies[j++] = dobj->dependencies[i];
711 dobj->nDeps = j;
716 * findTableByOid
717 * finds the entry (in tblinfo) of the table with the given oid
718 * returns NULL if not found
720 TableInfo *
721 findTableByOid(Oid oid)
723 return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
727 * findTypeByOid
728 * finds the entry (in typinfo) of the type with the given oid
729 * returns NULL if not found
731 TypeInfo *
732 findTypeByOid(Oid oid)
734 return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
738 * findFuncByOid
739 * finds the entry (in funinfo) of the function with the given oid
740 * returns NULL if not found
742 FuncInfo *
743 findFuncByOid(Oid oid)
745 return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
749 * findOprByOid
750 * finds the entry (in oprinfo) of the operator with the given oid
751 * returns NULL if not found
753 OprInfo *
754 findOprByOid(Oid oid)
756 return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
761 * findParentsByOid
762 * find a table's parents in tblinfo[]
764 static void
765 findParentsByOid(TableInfo *self,
766 InhInfo *inhinfo, int numInherits)
768 Oid oid = self->dobj.catId.oid;
769 int i,
771 int numParents;
773 numParents = 0;
774 for (i = 0; i < numInherits; i++)
776 if (inhinfo[i].inhrelid == oid)
777 numParents++;
780 self->numParents = numParents;
782 if (numParents > 0)
784 self->parents = (TableInfo **)
785 pg_malloc(sizeof(TableInfo *) * numParents);
786 j = 0;
787 for (i = 0; i < numInherits; i++)
789 if (inhinfo[i].inhrelid == oid)
791 TableInfo *parent;
793 parent = findTableByOid(inhinfo[i].inhparent);
794 if (parent == NULL)
796 write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
797 inhinfo[i].inhparent,
798 self->dobj.name,
799 oid);
800 exit_nicely();
802 self->parents[j++] = parent;
806 else
807 self->parents = NULL;
811 * parseOidArray
812 * parse a string of numbers delimited by spaces into a character array
814 * Note: actually this is used for both Oids and potentially-signed
815 * attribute numbers. This should cause no trouble, but we could split
816 * the function into two functions with different argument types if it does.
819 void
820 parseOidArray(const char *str, Oid *array, int arraysize)
822 int j,
823 argNum;
824 char temp[100];
825 char s;
827 argNum = 0;
828 j = 0;
829 for (;;)
831 s = *str++;
832 if (s == ' ' || s == '\0')
834 if (j > 0)
836 if (argNum >= arraysize)
838 write_msg(NULL, "could not parse numeric array \"%s\": too many numbers\n", str);
839 exit_nicely();
841 temp[j] = '\0';
842 array[argNum++] = atooid(temp);
843 j = 0;
845 if (s == '\0')
846 break;
848 else
850 if (!(isdigit((unsigned char) s) || s == '-') ||
851 j >= sizeof(temp) - 1)
853 write_msg(NULL, "could not parse numeric array \"%s\": invalid character in number\n", str);
854 exit_nicely();
856 temp[j++] = s;
860 while (argNum < arraysize)
861 array[argNum++] = InvalidOid;
866 * strInArray:
867 * takes in a string and a string array and the number of elements in the
868 * string array.
869 * returns the index if the string is somewhere in the array, -1 otherwise
872 static int
873 strInArray(const char *pattern, char **arr, int arr_size)
875 int i;
877 for (i = 0; i < arr_size; i++)
879 if (strcmp(pattern, arr[i]) == 0)
880 return i;
882 return -1;
887 * Support for simple list operations
890 void
891 simple_oid_list_append(SimpleOidList *list, Oid val)
893 SimpleOidListCell *cell;
895 cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
896 cell->next = NULL;
897 cell->val = val;
899 if (list->tail)
900 list->tail->next = cell;
901 else
902 list->head = cell;
903 list->tail = cell;
906 void
907 simple_string_list_append(SimpleStringList *list, const char *val)
909 SimpleStringListCell *cell;
911 /* this calculation correctly accounts for the null trailing byte */
912 cell = (SimpleStringListCell *)
913 pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
914 cell->next = NULL;
915 strcpy(cell->val, val);
917 if (list->tail)
918 list->tail->next = cell;
919 else
920 list->head = cell;
921 list->tail = cell;
924 bool
925 simple_oid_list_member(SimpleOidList *list, Oid val)
927 SimpleOidListCell *cell;
929 for (cell = list->head; cell; cell = cell->next)
931 if (cell->val == val)
932 return true;
934 return false;
937 bool
938 simple_string_list_member(SimpleStringList *list, const char *val)
940 SimpleStringListCell *cell;
942 for (cell = list->head; cell; cell = cell->next)
944 if (strcmp(cell->val, val) == 0)
945 return true;
947 return false;
952 * Safer versions of some standard C library functions. If an
953 * out-of-memory condition occurs, these functions will bail out
954 * safely; therefore, their return value is guaranteed to be non-NULL.
956 * XXX need to refactor things so that these can be in a file that can be
957 * shared by pg_dumpall and pg_restore as well as pg_dump.
960 char *
961 pg_strdup(const char *string)
963 char *tmp;
965 if (!string)
966 exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
967 tmp = strdup(string);
968 if (!tmp)
969 exit_horribly(NULL, NULL, "out of memory\n");
970 return tmp;
973 void *
974 pg_malloc(size_t size)
976 void *tmp;
978 tmp = malloc(size);
979 if (!tmp)
980 exit_horribly(NULL, NULL, "out of memory\n");
981 return tmp;
984 void *
985 pg_calloc(size_t nmemb, size_t size)
987 void *tmp;
989 tmp = calloc(nmemb, size);
990 if (!tmp)
991 exit_horribly(NULL, NULL, "out of memory\n");
992 return tmp;
995 void *
996 pg_realloc(void *ptr, size_t size)
998 void *tmp;
1000 tmp = realloc(ptr, size);
1001 if (!tmp)
1002 exit_horribly(NULL, NULL, "out of memory\n");
1003 return tmp;