From 46651ce6fe013220ed397add242004d764fc0153 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:15:05 +0200 Subject: Adding upstream version 14.5. Signed-off-by: Daniel Baumann --- src/bin/pg_dump/.gitignore | 5 + src/bin/pg_dump/Makefile | 65 + src/bin/pg_dump/common.c | 1187 ++ src/bin/pg_dump/compress_io.c | 717 + src/bin/pg_dump/compress_io.h | 70 + src/bin/pg_dump/dumputils.c | 1045 ++ src/bin/pg_dump/dumputils.h | 69 + src/bin/pg_dump/nls.mk | 18 + src/bin/pg_dump/parallel.c | 1806 +++ src/bin/pg_dump/parallel.h | 70 + src/bin/pg_dump/pg_backup.h | 306 + src/bin/pg_dump/pg_backup_archiver.c | 4824 +++++++ src/bin/pg_dump/pg_backup_archiver.h | 487 + src/bin/pg_dump/pg_backup_custom.c | 1022 ++ src/bin/pg_dump/pg_backup_db.c | 573 + src/bin/pg_dump/pg_backup_db.h | 26 + src/bin/pg_dump/pg_backup_directory.c | 851 ++ src/bin/pg_dump/pg_backup_null.c | 228 + src/bin/pg_dump/pg_backup_tar.c | 1306 ++ src/bin/pg_dump/pg_backup_tar.h | 37 + src/bin/pg_dump/pg_backup_utils.c | 108 + src/bin/pg_dump/pg_backup_utils.h | 36 + src/bin/pg_dump/pg_dump.c | 18953 +++++++++++++++++++++++++ src/bin/pg_dump/pg_dump.h | 739 + src/bin/pg_dump/pg_dump_sort.c | 1510 ++ src/bin/pg_dump/pg_dumpall.c | 1944 +++ src/bin/pg_dump/pg_restore.c | 524 + src/bin/pg_dump/po/cs.po | 2965 ++++ src/bin/pg_dump/po/de.po | 2751 ++++ src/bin/pg_dump/po/el.po | 2713 ++++ src/bin/pg_dump/po/es.po | 2757 ++++ src/bin/pg_dump/po/fr.po | 3345 +++++ src/bin/pg_dump/po/ja.po | 2744 ++++ src/bin/pg_dump/po/ko.po | 2821 ++++ src/bin/pg_dump/po/ru.po | 3435 +++++ src/bin/pg_dump/po/sv.po | 2718 ++++ src/bin/pg_dump/po/tr.po | 3070 ++++ src/bin/pg_dump/po/uk.po | 2665 ++++ src/bin/pg_dump/po/zh_CN.po | 2643 ++++ src/bin/pg_dump/t/001_basic.pl | 190 + src/bin/pg_dump/t/002_pg_dump.pl | 3940 +++++ src/bin/pg_dump/t/003_pg_dump_with_server.pl | 39 + src/bin/pg_dump/t/010_dump_connstr.pl | 231 + 43 files changed, 77553 insertions(+) create mode 100644 src/bin/pg_dump/.gitignore create mode 100644 src/bin/pg_dump/Makefile create mode 100644 src/bin/pg_dump/common.c create mode 100644 src/bin/pg_dump/compress_io.c create mode 100644 src/bin/pg_dump/compress_io.h create mode 100644 src/bin/pg_dump/dumputils.c create mode 100644 src/bin/pg_dump/dumputils.h create mode 100644 src/bin/pg_dump/nls.mk create mode 100644 src/bin/pg_dump/parallel.c create mode 100644 src/bin/pg_dump/parallel.h create mode 100644 src/bin/pg_dump/pg_backup.h create mode 100644 src/bin/pg_dump/pg_backup_archiver.c create mode 100644 src/bin/pg_dump/pg_backup_archiver.h create mode 100644 src/bin/pg_dump/pg_backup_custom.c create mode 100644 src/bin/pg_dump/pg_backup_db.c create mode 100644 src/bin/pg_dump/pg_backup_db.h create mode 100644 src/bin/pg_dump/pg_backup_directory.c create mode 100644 src/bin/pg_dump/pg_backup_null.c create mode 100644 src/bin/pg_dump/pg_backup_tar.c create mode 100644 src/bin/pg_dump/pg_backup_tar.h create mode 100644 src/bin/pg_dump/pg_backup_utils.c create mode 100644 src/bin/pg_dump/pg_backup_utils.h create mode 100644 src/bin/pg_dump/pg_dump.c create mode 100644 src/bin/pg_dump/pg_dump.h create mode 100644 src/bin/pg_dump/pg_dump_sort.c create mode 100644 src/bin/pg_dump/pg_dumpall.c create mode 100644 src/bin/pg_dump/pg_restore.c create mode 100644 src/bin/pg_dump/po/cs.po create mode 100644 src/bin/pg_dump/po/de.po create mode 100644 src/bin/pg_dump/po/el.po create mode 100644 src/bin/pg_dump/po/es.po create mode 100644 src/bin/pg_dump/po/fr.po create mode 100644 src/bin/pg_dump/po/ja.po create mode 100644 src/bin/pg_dump/po/ko.po create mode 100644 src/bin/pg_dump/po/ru.po create mode 100644 src/bin/pg_dump/po/sv.po create mode 100644 src/bin/pg_dump/po/tr.po create mode 100644 src/bin/pg_dump/po/uk.po create mode 100644 src/bin/pg_dump/po/zh_CN.po create mode 100644 src/bin/pg_dump/t/001_basic.pl create mode 100644 src/bin/pg_dump/t/002_pg_dump.pl create mode 100644 src/bin/pg_dump/t/003_pg_dump_with_server.pl create mode 100644 src/bin/pg_dump/t/010_dump_connstr.pl (limited to 'src/bin/pg_dump') diff --git a/src/bin/pg_dump/.gitignore b/src/bin/pg_dump/.gitignore new file mode 100644 index 0000000..e6d7812 --- /dev/null +++ b/src/bin/pg_dump/.gitignore @@ -0,0 +1,5 @@ +/pg_dump +/pg_dumpall +/pg_restore + +/tmp_check/ diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile new file mode 100644 index 0000000..b8b2628 --- /dev/null +++ b/src/bin/pg_dump/Makefile @@ -0,0 +1,65 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/bin/pg_dump +# +# Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/bin/pg_dump/Makefile +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pg_dump/pg_restore/pg_dumpall - backup and restore PostgreSQL databases" +PGAPPICON=win32 + +subdir = src/bin/pg_dump +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) +LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport) + +OBJS = \ + $(WIN32RES) \ + compress_io.o \ + dumputils.o \ + parallel.o \ + pg_backup_archiver.o \ + pg_backup_custom.o \ + pg_backup_db.o \ + pg_backup_directory.o \ + pg_backup_null.o \ + pg_backup_tar.o \ + pg_backup_utils.o + +all: pg_dump pg_restore pg_dumpall + +pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils + $(CC) $(CFLAGS) pg_dump.o common.o pg_dump_sort.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +pg_restore: pg_restore.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils + $(CC) $(CFLAGS) pg_restore.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +pg_dumpall: pg_dumpall.o dumputils.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils + $(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(WIN32RES) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X) + $(INSTALL_PROGRAM) pg_restore$(X) '$(DESTDIR)$(bindir)'/pg_restore$(X) + $(INSTALL_PROGRAM) pg_dumpall$(X) '$(DESTDIR)$(bindir)'/pg_dumpall$(X) + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +uninstall: + rm -f $(addprefix '$(DESTDIR)$(bindir)'/, pg_dump$(X) pg_restore$(X) pg_dumpall$(X)) + +clean distclean maintainer-clean: + rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_dump_sort.o pg_restore.o pg_dumpall.o + rm -rf tmp_check diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c new file mode 100644 index 0000000..1f24e79 --- /dev/null +++ b/src/bin/pg_dump/common.c @@ -0,0 +1,1187 @@ +/*------------------------------------------------------------------------- + * + * common.c + * Catalog routines used by pg_dump; long ago these were shared + * by another dump tool, but not anymore. + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/bin/pg_dump/common.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include + +#include "catalog/pg_class_d.h" +#include "fe_utils/string_utils.h" +#include "pg_backup_archiver.h" +#include "pg_backup_utils.h" +#include "pg_dump.h" + +/* + * Variables for mapping DumpId to DumpableObject + */ +static DumpableObject **dumpIdMap = NULL; +static int allocedDumpIds = 0; +static DumpId lastDumpId = 0; /* Note: 0 is InvalidDumpId */ + +/* + * Variables for mapping CatalogId to DumpableObject + */ +static bool catalogIdMapValid = false; +static DumpableObject **catalogIdMap = NULL; +static int numCatalogIds = 0; + +/* + * These variables are static to avoid the notational cruft of having to pass + * them into findTableByOid() and friends. For each of these arrays, we build + * a sorted-by-OID index array immediately after the objects are fetched, + * and then we use binary search in findTableByOid() and friends. (qsort'ing + * the object arrays themselves would be simpler, but it doesn't work because + * pg_dump.c may have already established pointers between items.) + */ +static DumpableObject **tblinfoindex; +static DumpableObject **typinfoindex; +static DumpableObject **funinfoindex; +static DumpableObject **oprinfoindex; +static DumpableObject **collinfoindex; +static DumpableObject **nspinfoindex; +static DumpableObject **extinfoindex; +static DumpableObject **pubinfoindex; +static int numTables; +static int numTypes; +static int numFuncs; +static int numOperators; +static int numCollations; +static int numNamespaces; +static int numExtensions; +static int numPublications; + +/* This is an array of object identities, not actual DumpableObjects */ +static ExtensionMemberId *extmembers; +static int numextmembers; + +static void flagInhTables(Archive *fout, TableInfo *tbinfo, int numTables, + InhInfo *inhinfo, int numInherits); +static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables); +static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables); +static DumpableObject **buildIndexArray(void *objArray, int numObjs, + Size objSize); +static int DOCatalogIdCompare(const void *p1, const void *p2); +static int ExtensionMemberIdCompare(const void *p1, const void *p2); +static void findParentsByOid(TableInfo *self, + InhInfo *inhinfo, int numInherits); +static int strInArray(const char *pattern, char **arr, int arr_size); +static IndxInfo *findIndexByOid(Oid oid, DumpableObject **idxinfoindex, + int numIndexes); + + +/* + * getSchemaData + * Collect information about all potentially dumpable objects + */ +TableInfo * +getSchemaData(Archive *fout, int *numTablesPtr) +{ + TableInfo *tblinfo; + TypeInfo *typinfo; + FuncInfo *funinfo; + OprInfo *oprinfo; + CollInfo *collinfo; + NamespaceInfo *nspinfo; + ExtensionInfo *extinfo; + PublicationInfo *pubinfo; + InhInfo *inhinfo; + int numAggregates; + int numInherits; + int numRules; + int numProcLangs; + int numCasts; + int numTransforms; + int numAccessMethods; + int numOpclasses; + int numOpfamilies; + int numConversions; + int numTSParsers; + int numTSTemplates; + int numTSDicts; + int numTSConfigs; + int numForeignDataWrappers; + int numForeignServers; + int numDefaultACLs; + int numEventTriggers; + + /* + * We must read extensions and extension membership info first, because + * extension membership needs to be consultable during decisions about + * whether other objects are to be dumped. + */ + pg_log_info("reading extensions"); + extinfo = getExtensions(fout, &numExtensions); + extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo)); + + pg_log_info("identifying extension members"); + getExtensionMembership(fout, extinfo, numExtensions); + + pg_log_info("reading schemas"); + nspinfo = getNamespaces(fout, &numNamespaces); + nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo)); + + /* + * getTables should be done as soon as possible, so as to minimize the + * window between starting our transaction and acquiring per-table locks. + * However, we have to do getNamespaces first because the tables get + * linked to their containing namespaces during getTables. + */ + pg_log_info("reading user-defined tables"); + tblinfo = getTables(fout, &numTables); + tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo)); + + /* Do this after we've built tblinfoindex */ + getOwnedSeqs(fout, tblinfo, numTables); + + pg_log_info("reading user-defined functions"); + funinfo = getFuncs(fout, &numFuncs); + funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo)); + + /* this must be after getTables and getFuncs */ + pg_log_info("reading user-defined types"); + typinfo = getTypes(fout, &numTypes); + typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo)); + + /* this must be after getFuncs, too */ + pg_log_info("reading procedural languages"); + getProcLangs(fout, &numProcLangs); + + pg_log_info("reading user-defined aggregate functions"); + getAggregates(fout, &numAggregates); + + pg_log_info("reading user-defined operators"); + oprinfo = getOperators(fout, &numOperators); + oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo)); + + pg_log_info("reading user-defined access methods"); + getAccessMethods(fout, &numAccessMethods); + + pg_log_info("reading user-defined operator classes"); + getOpclasses(fout, &numOpclasses); + + pg_log_info("reading user-defined operator families"); + getOpfamilies(fout, &numOpfamilies); + + pg_log_info("reading user-defined text search parsers"); + getTSParsers(fout, &numTSParsers); + + pg_log_info("reading user-defined text search templates"); + getTSTemplates(fout, &numTSTemplates); + + pg_log_info("reading user-defined text search dictionaries"); + getTSDictionaries(fout, &numTSDicts); + + pg_log_info("reading user-defined text search configurations"); + getTSConfigurations(fout, &numTSConfigs); + + pg_log_info("reading user-defined foreign-data wrappers"); + getForeignDataWrappers(fout, &numForeignDataWrappers); + + pg_log_info("reading user-defined foreign servers"); + getForeignServers(fout, &numForeignServers); + + pg_log_info("reading default privileges"); + getDefaultACLs(fout, &numDefaultACLs); + + pg_log_info("reading user-defined collations"); + collinfo = getCollations(fout, &numCollations); + collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo)); + + pg_log_info("reading user-defined conversions"); + getConversions(fout, &numConversions); + + pg_log_info("reading type casts"); + getCasts(fout, &numCasts); + + pg_log_info("reading transforms"); + getTransforms(fout, &numTransforms); + + pg_log_info("reading table inheritance information"); + inhinfo = getInherits(fout, &numInherits); + + pg_log_info("reading event triggers"); + getEventTriggers(fout, &numEventTriggers); + + /* Identify extension configuration tables that should be dumped */ + pg_log_info("finding extension tables"); + processExtensionTables(fout, extinfo, numExtensions); + + /* Link tables to parents, mark parents of target tables interesting */ + pg_log_info("finding inheritance relationships"); + flagInhTables(fout, tblinfo, numTables, inhinfo, numInherits); + + pg_log_info("reading column info for interesting tables"); + getTableAttrs(fout, tblinfo, numTables); + + pg_log_info("flagging inherited columns in subtables"); + flagInhAttrs(fout->dopt, tblinfo, numTables); + + pg_log_info("reading indexes"); + getIndexes(fout, tblinfo, numTables); + + pg_log_info("flagging indexes in partitioned tables"); + flagInhIndexes(fout, tblinfo, numTables); + + pg_log_info("reading extended statistics"); + getExtendedStatistics(fout); + + pg_log_info("reading constraints"); + getConstraints(fout, tblinfo, numTables); + + pg_log_info("reading triggers"); + getTriggers(fout, tblinfo, numTables); + + pg_log_info("reading rewrite rules"); + getRules(fout, &numRules); + + pg_log_info("reading policies"); + getPolicies(fout, tblinfo, numTables); + + pg_log_info("reading publications"); + pubinfo = getPublications(fout, &numPublications); + pubinfoindex = buildIndexArray(pubinfo, numPublications, + sizeof(PublicationInfo)); + + pg_log_info("reading publication membership"); + getPublicationTables(fout, tblinfo, numTables); + + pg_log_info("reading subscriptions"); + getSubscriptions(fout); + + *numTablesPtr = numTables; + return tblinfo; +} + +/* flagInhTables - + * Fill in parent link fields of tables for which we need that information, + * mark parents of target tables as interesting, and create + * TableAttachInfo objects for partitioned tables with appropriate + * dependency links. + * + * 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(Archive *fout, TableInfo *tblinfo, int numTables, + InhInfo *inhinfo, int numInherits) +{ + DumpOptions *dopt = fout->dopt; + int i, + j; + + for (i = 0; i < numTables; i++) + { + bool find_parents = true; + bool mark_parents = true; + + /* Some kinds never have parents */ + if (tblinfo[i].relkind == RELKIND_SEQUENCE || + tblinfo[i].relkind == RELKIND_VIEW || + tblinfo[i].relkind == RELKIND_MATVIEW) + continue; + + /* + * Normally, we don't bother computing anything for non-target tables, + * but if load-via-partition-root is specified, we gather information + * on every partition in the system so that getRootTableInfo can trace + * from any given to leaf partition all the way up to the root. (We + * don't need to mark them as interesting for getTableAttrs, though.) + */ + if (!tblinfo[i].dobj.dump) + { + mark_parents = false; + + if (!dopt->load_via_partition_root || + !tblinfo[i].ispartition) + find_parents = false; + } + + /* If needed, find all the immediate parent tables. */ + if (find_parents) + findParentsByOid(&tblinfo[i], inhinfo, numInherits); + + /* + * If needed, mark the parents as interesting for getTableAttrs and + * getIndexes. + */ + if (mark_parents) + { + int numParents = tblinfo[i].numParents; + TableInfo **parents = tblinfo[i].parents; + + for (j = 0; j < numParents; j++) + parents[j]->interesting = true; + } + + /* Create TableAttachInfo object if needed */ + if (tblinfo[i].dobj.dump && tblinfo[i].ispartition) + { + TableAttachInfo *attachinfo; + + /* With partitions there can only be one parent */ + if (tblinfo[i].numParents != 1) + fatal("invalid number of parents %d for table \"%s\"", + tblinfo[i].numParents, + tblinfo[i].dobj.name); + + attachinfo = (TableAttachInfo *) palloc(sizeof(TableAttachInfo)); + attachinfo->dobj.objType = DO_TABLE_ATTACH; + attachinfo->dobj.catId.tableoid = 0; + attachinfo->dobj.catId.oid = 0; + AssignDumpId(&attachinfo->dobj); + attachinfo->dobj.name = pg_strdup(tblinfo[i].dobj.name); + attachinfo->dobj.namespace = tblinfo[i].dobj.namespace; + attachinfo->parentTbl = tblinfo[i].parents[0]; + attachinfo->partitionTbl = &tblinfo[i]; + + /* + * We must state the DO_TABLE_ATTACH object's dependencies + * explicitly, since it will not match anything in pg_depend. + * + * Give it dependencies on both the partition table and the parent + * table, so that it will not be executed till both of those + * exist. (There's no need to care what order those are created + * in.) + */ + addObjectDependency(&attachinfo->dobj, tblinfo[i].dobj.dumpId); + addObjectDependency(&attachinfo->dobj, tblinfo[i].parents[0]->dobj.dumpId); + } + } +} + +/* + * flagInhIndexes - + * Create IndexAttachInfo objects for partitioned indexes, and add + * appropriate dependency links. + */ +static void +flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i, + j, + k; + DumpableObject ***parentIndexArray; + + parentIndexArray = (DumpableObject ***) + pg_malloc0(getMaxDumpId() * sizeof(DumpableObject **)); + + for (i = 0; i < numTables; i++) + { + TableInfo *parenttbl; + IndexAttachInfo *attachinfo; + + if (!tblinfo[i].ispartition || tblinfo[i].numParents == 0) + continue; + + Assert(tblinfo[i].numParents == 1); + parenttbl = tblinfo[i].parents[0]; + + /* + * We need access to each parent table's index list, but there is no + * index to cover them outside of this function. To avoid having to + * sort every parent table's indexes each time we come across each of + * its partitions, create an indexed array for each parent the first + * time it is required. + */ + if (parentIndexArray[parenttbl->dobj.dumpId] == NULL) + parentIndexArray[parenttbl->dobj.dumpId] = + buildIndexArray(parenttbl->indexes, + parenttbl->numIndexes, + sizeof(IndxInfo)); + + attachinfo = (IndexAttachInfo *) + pg_malloc0(tblinfo[i].numIndexes * sizeof(IndexAttachInfo)); + for (j = 0, k = 0; j < tblinfo[i].numIndexes; j++) + { + IndxInfo *index = &(tblinfo[i].indexes[j]); + IndxInfo *parentidx; + + if (index->parentidx == 0) + continue; + + parentidx = findIndexByOid(index->parentidx, + parentIndexArray[parenttbl->dobj.dumpId], + parenttbl->numIndexes); + if (parentidx == NULL) + continue; + + attachinfo[k].dobj.objType = DO_INDEX_ATTACH; + attachinfo[k].dobj.catId.tableoid = 0; + attachinfo[k].dobj.catId.oid = 0; + AssignDumpId(&attachinfo[k].dobj); + attachinfo[k].dobj.name = pg_strdup(index->dobj.name); + attachinfo[k].dobj.namespace = index->indextable->dobj.namespace; + attachinfo[k].parentIdx = parentidx; + attachinfo[k].partitionIdx = index; + + /* + * We must state the DO_INDEX_ATTACH object's dependencies + * explicitly, since it will not match anything in pg_depend. + * + * Give it dependencies on both the partition index and the parent + * index, so that it will not be executed till both of those + * exist. (There's no need to care what order those are created + * in.) + * + * In addition, give it dependencies on the indexes' underlying + * tables. This does nothing of great value so far as serial + * restore ordering goes, but it ensures that a parallel restore + * will not try to run the ATTACH concurrently with other + * operations on those tables. + */ + addObjectDependency(&attachinfo[k].dobj, index->dobj.dumpId); + addObjectDependency(&attachinfo[k].dobj, parentidx->dobj.dumpId); + addObjectDependency(&attachinfo[k].dobj, + index->indextable->dobj.dumpId); + addObjectDependency(&attachinfo[k].dobj, + parentidx->indextable->dobj.dumpId); + + /* keep track of the list of partitions in the parent index */ + simple_ptr_list_append(&parentidx->partattaches, &attachinfo[k].dobj); + + k++; + } + } + + for (i = 0; i < numTables; i++) + if (parentIndexArray[i]) + pg_free(parentIndexArray[i]); + pg_free(parentIndexArray); +} + +/* flagInhAttrs - + * for each dumpable table in tblinfo, flag its inherited attributes + * + * What we need to do here is: + * + * - Detect child columns that inherit NOT NULL bits from their parents, so + * that we needn't specify that again for the child. + * + * - Detect child columns that have DEFAULT NULL when their parents had some + * non-null default. In this case, we make up a dummy AttrDefInfo object so + * that we'll correctly emit the necessary DEFAULT NULL clause; otherwise + * the backend will apply an inherited default to the column. + * + * - Detect child columns that have a generation expression when their parents + * also have one. Generation expressions are always inherited, so there is + * no need to set them again in child tables, and there is no syntax for it + * either. Exceptions: If it's a partition or we are in binary upgrade + * mode, we dump them because in those cases inherited tables are recreated + * standalone first and then reattached to the parent. (See also the logic + * in dumpTableSchema().) In that situation, the generation expressions + * must match the parent, enforced by ALTER TABLE. + * + * modifies tblinfo + */ +static void +flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables) +{ + int i, + j, + k; + + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &(tblinfo[i]); + int numParents; + TableInfo **parents; + + /* Some kinds never have parents */ + if (tbinfo->relkind == RELKIND_SEQUENCE || + tbinfo->relkind == RELKIND_VIEW || + tbinfo->relkind == RELKIND_MATVIEW) + continue; + + /* Don't bother computing anything for non-target tables, either */ + if (!tbinfo->dobj.dump) + continue; + + numParents = tbinfo->numParents; + parents = tbinfo->parents; + + if (numParents == 0) + continue; /* nothing to see here, move along */ + + /* For each column, search for matching column names in parent(s) */ + for (j = 0; j < tbinfo->numatts; j++) + { + bool foundNotNull; /* Attr was NOT NULL in a parent */ + bool foundDefault; /* Found a default in a parent */ + bool foundGenerated; /* Found a generated in a parent */ + + /* no point in examining dropped columns */ + if (tbinfo->attisdropped[j]) + continue; + + foundNotNull = false; + foundDefault = false; + foundGenerated = false; + for (k = 0; k < numParents; k++) + { + TableInfo *parent = parents[k]; + int inhAttrInd; + + inhAttrInd = strInArray(tbinfo->attnames[j], + parent->attnames, + parent->numatts); + if (inhAttrInd >= 0) + { + foundNotNull |= parent->notnull[inhAttrInd]; + foundDefault |= (parent->attrdefs[inhAttrInd] != NULL && !parent->attgenerated[inhAttrInd]); + foundGenerated |= parent->attgenerated[inhAttrInd]; + } + } + + /* Remember if we found inherited NOT NULL */ + tbinfo->inhNotNull[j] = foundNotNull; + + /* Manufacture a DEFAULT NULL clause if necessary */ + if (foundDefault && tbinfo->attrdefs[j] == NULL) + { + AttrDefInfo *attrDef; + + attrDef = (AttrDefInfo *) pg_malloc(sizeof(AttrDefInfo)); + attrDef->dobj.objType = DO_ATTRDEF; + attrDef->dobj.catId.tableoid = 0; + attrDef->dobj.catId.oid = 0; + AssignDumpId(&attrDef->dobj); + attrDef->dobj.name = pg_strdup(tbinfo->dobj.name); + attrDef->dobj.namespace = tbinfo->dobj.namespace; + attrDef->dobj.dump = tbinfo->dobj.dump; + + attrDef->adtable = tbinfo; + attrDef->adnum = j + 1; + attrDef->adef_expr = pg_strdup("NULL"); + + /* Will column be dumped explicitly? */ + if (shouldPrintColumn(dopt, tbinfo, j)) + { + attrDef->separate = false; + /* No dependency needed: NULL cannot have dependencies */ + } + else + { + /* column will be suppressed, print default separately */ + attrDef->separate = true; + /* ensure it comes out after the table */ + addObjectDependency(&attrDef->dobj, + tbinfo->dobj.dumpId); + } + + tbinfo->attrdefs[j] = attrDef; + } + + /* Remove generation expression from child */ + if (foundGenerated && !tbinfo->ispartition && !dopt->binary_upgrade) + tbinfo->attrdefs[j] = NULL; + } + } +} + +/* + * AssignDumpId + * Given a newly-created dumpable object, assign a dump ID, + * and enter the object into the lookup table. + * + * The caller is expected to have filled in objType and catId, + * but not any of the other standard fields of a DumpableObject. + */ +void +AssignDumpId(DumpableObject *dobj) +{ + dobj->dumpId = ++lastDumpId; + dobj->name = NULL; /* must be set later */ + dobj->namespace = NULL; /* may be set later */ + dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */ + dobj->dump_contains = DUMP_COMPONENT_ALL; /* default assumption */ + dobj->ext_member = false; /* default assumption */ + dobj->depends_on_ext = false; /* default assumption */ + dobj->dependencies = NULL; + dobj->nDeps = 0; + dobj->allocDeps = 0; + + while (dobj->dumpId >= allocedDumpIds) + { + int newAlloc; + + if (allocedDumpIds <= 0) + { + newAlloc = 256; + dumpIdMap = (DumpableObject **) + pg_malloc(newAlloc * sizeof(DumpableObject *)); + } + else + { + newAlloc = allocedDumpIds * 2; + dumpIdMap = (DumpableObject **) + pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *)); + } + memset(dumpIdMap + allocedDumpIds, 0, + (newAlloc - allocedDumpIds) * sizeof(DumpableObject *)); + allocedDumpIds = newAlloc; + } + dumpIdMap[dobj->dumpId] = dobj; + + /* mark catalogIdMap invalid, but don't rebuild it yet */ + catalogIdMapValid = false; +} + +/* + * Assign a DumpId that's not tied to a DumpableObject. + * + * This is used when creating a "fixed" ArchiveEntry that doesn't need to + * participate in the sorting logic. + */ +DumpId +createDumpId(void) +{ + return ++lastDumpId; +} + +/* + * Return the largest DumpId so far assigned + */ +DumpId +getMaxDumpId(void) +{ + return lastDumpId; +} + +/* + * Find a DumpableObject by dump ID + * + * Returns NULL for invalid ID + */ +DumpableObject * +findObjectByDumpId(DumpId dumpId) +{ + if (dumpId <= 0 || dumpId >= allocedDumpIds) + return NULL; /* out of range? */ + return dumpIdMap[dumpId]; +} + +/* + * Find a DumpableObject by catalog ID + * + * Returns NULL for unknown ID + * + * We use binary search in a sorted list that is built on first call. + * If AssignDumpId() and findObjectByCatalogId() calls were freely intermixed, + * the code would work, but possibly be very slow. In the current usage + * pattern that does not happen, indeed we build the list at most twice. + */ +DumpableObject * +findObjectByCatalogId(CatalogId catalogId) +{ + DumpableObject **low; + DumpableObject **high; + + if (!catalogIdMapValid) + { + if (catalogIdMap) + free(catalogIdMap); + getDumpableObjects(&catalogIdMap, &numCatalogIds); + if (numCatalogIds > 1) + qsort((void *) catalogIdMap, numCatalogIds, + sizeof(DumpableObject *), DOCatalogIdCompare); + catalogIdMapValid = true; + } + + /* + * We could use bsearch() here, but the notational cruft of calling + * bsearch is nearly as bad as doing it ourselves; and the generalized + * bsearch function is noticeably slower as well. + */ + if (numCatalogIds <= 0) + return NULL; + low = catalogIdMap; + high = catalogIdMap + (numCatalogIds - 1); + while (low <= high) + { + DumpableObject **middle; + int difference; + + middle = low + (high - low) / 2; + /* comparison must match DOCatalogIdCompare, below */ + difference = oidcmp((*middle)->catId.oid, catalogId.oid); + if (difference == 0) + difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid); + if (difference == 0) + return *middle; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + return NULL; +} + +/* + * Find a DumpableObject by OID, in a pre-sorted array of one type of object + * + * Returns NULL for unknown OID + */ +static DumpableObject * +findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs) +{ + DumpableObject **low; + DumpableObject **high; + + /* + * This is the same as findObjectByCatalogId except we assume we need not + * look at table OID because the objects are all the same type. + * + * We could use bsearch() here, but the notational cruft of calling + * bsearch is nearly as bad as doing it ourselves; and the generalized + * bsearch function is noticeably slower as well. + */ + if (numObjs <= 0) + return NULL; + low = indexArray; + high = indexArray + (numObjs - 1); + while (low <= high) + { + DumpableObject **middle; + int difference; + + middle = low + (high - low) / 2; + difference = oidcmp((*middle)->catId.oid, oid); + if (difference == 0) + return *middle; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + return NULL; +} + +/* + * Build an index array of DumpableObject pointers, sorted by OID + */ +static DumpableObject ** +buildIndexArray(void *objArray, int numObjs, Size objSize) +{ + DumpableObject **ptrs; + int i; + + if (numObjs <= 0) + return NULL; + + ptrs = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *)); + for (i = 0; i < numObjs; i++) + ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize); + + /* We can use DOCatalogIdCompare to sort since its first key is OID */ + if (numObjs > 1) + qsort((void *) ptrs, numObjs, sizeof(DumpableObject *), + DOCatalogIdCompare); + + return ptrs; +} + +/* + * qsort comparator for pointers to DumpableObjects + */ +static int +DOCatalogIdCompare(const void *p1, const void *p2) +{ + const DumpableObject *obj1 = *(DumpableObject *const *) p1; + const DumpableObject *obj2 = *(DumpableObject *const *) p2; + int cmpval; + + /* + * Compare OID first since it's usually unique, whereas there will only be + * a few distinct values of tableoid. + */ + cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid); + if (cmpval == 0) + cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid); + return cmpval; +} + +/* + * Build an array of pointers to all known dumpable objects + * + * This simply creates a modifiable copy of the internal map. + */ +void +getDumpableObjects(DumpableObject ***objs, int *numObjs) +{ + int i, + j; + + *objs = (DumpableObject **) + pg_malloc(allocedDumpIds * sizeof(DumpableObject *)); + j = 0; + for (i = 1; i < allocedDumpIds; i++) + { + if (dumpIdMap[i]) + (*objs)[j++] = dumpIdMap[i]; + } + *numObjs = j; +} + +/* + * Add a dependency link to a DumpableObject + * + * Note: duplicate dependencies are currently not eliminated + */ +void +addObjectDependency(DumpableObject *dobj, DumpId refId) +{ + if (dobj->nDeps >= dobj->allocDeps) + { + if (dobj->allocDeps <= 0) + { + dobj->allocDeps = 16; + dobj->dependencies = (DumpId *) + pg_malloc(dobj->allocDeps * sizeof(DumpId)); + } + else + { + dobj->allocDeps *= 2; + dobj->dependencies = (DumpId *) + pg_realloc(dobj->dependencies, + dobj->allocDeps * sizeof(DumpId)); + } + } + dobj->dependencies[dobj->nDeps++] = refId; +} + +/* + * Remove a dependency link from a DumpableObject + * + * If there are multiple links, all are removed + */ +void +removeObjectDependency(DumpableObject *dobj, DumpId refId) +{ + int i; + int j = 0; + + for (i = 0; i < dobj->nDeps; i++) + { + if (dobj->dependencies[i] != refId) + dobj->dependencies[j++] = dobj->dependencies[i]; + } + dobj->nDeps = j; +} + + +/* + * findTableByOid + * finds the entry (in tblinfo) of the table with the given oid + * returns NULL if not found + */ +TableInfo * +findTableByOid(Oid oid) +{ + return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables); +} + +/* + * findTypeByOid + * finds the entry (in typinfo) of the type with the given oid + * returns NULL if not found + */ +TypeInfo * +findTypeByOid(Oid oid) +{ + return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes); +} + +/* + * findFuncByOid + * finds the entry (in funinfo) of the function with the given oid + * returns NULL if not found + */ +FuncInfo * +findFuncByOid(Oid oid) +{ + return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs); +} + +/* + * findOprByOid + * finds the entry (in oprinfo) of the operator with the given oid + * returns NULL if not found + */ +OprInfo * +findOprByOid(Oid oid) +{ + return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators); +} + +/* + * findCollationByOid + * finds the entry (in collinfo) of the collation with the given oid + * returns NULL if not found + */ +CollInfo * +findCollationByOid(Oid oid) +{ + return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations); +} + +/* + * findNamespaceByOid + * finds the entry (in nspinfo) of the namespace with the given oid + * returns NULL if not found + */ +NamespaceInfo * +findNamespaceByOid(Oid oid) +{ + return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces); +} + +/* + * findExtensionByOid + * finds the entry (in extinfo) of the extension with the given oid + * returns NULL if not found + */ +ExtensionInfo * +findExtensionByOid(Oid oid) +{ + return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions); +} + +/* + * findPublicationByOid + * finds the entry (in pubinfo) of the publication with the given oid + * returns NULL if not found + */ +PublicationInfo * +findPublicationByOid(Oid oid) +{ + return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications); +} + +/* + * findIndexByOid + * find the entry of the index with the given oid + * + * This one's signature is different from the previous ones because we lack a + * global array of all indexes, so caller must pass their array as argument. + */ +static IndxInfo * +findIndexByOid(Oid oid, DumpableObject **idxinfoindex, int numIndexes) +{ + return (IndxInfo *) findObjectByOid(oid, idxinfoindex, numIndexes); +} + +/* + * setExtensionMembership + * accept and save data about which objects belong to extensions + */ +void +setExtensionMembership(ExtensionMemberId *extmems, int nextmems) +{ + /* Sort array in preparation for binary searches */ + if (nextmems > 1) + qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId), + ExtensionMemberIdCompare); + /* And save */ + extmembers = extmems; + numextmembers = nextmems; +} + +/* + * findOwningExtension + * return owning extension for specified catalog ID, or NULL if none + */ +ExtensionInfo * +findOwningExtension(CatalogId catalogId) +{ + ExtensionMemberId *low; + ExtensionMemberId *high; + + /* + * We could use bsearch() here, but the notational cruft of calling + * bsearch is nearly as bad as doing it ourselves; and the generalized + * bsearch function is noticeably slower as well. + */ + if (numextmembers <= 0) + return NULL; + low = extmembers; + high = extmembers + (numextmembers - 1); + while (low <= high) + { + ExtensionMemberId *middle; + int difference; + + middle = low + (high - low) / 2; + /* comparison must match ExtensionMemberIdCompare, below */ + difference = oidcmp(middle->catId.oid, catalogId.oid); + if (difference == 0) + difference = oidcmp(middle->catId.tableoid, catalogId.tableoid); + if (difference == 0) + return middle->ext; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + return NULL; +} + +/* + * qsort comparator for ExtensionMemberIds + */ +static int +ExtensionMemberIdCompare(const void *p1, const void *p2) +{ + const ExtensionMemberId *obj1 = (const ExtensionMemberId *) p1; + const ExtensionMemberId *obj2 = (const ExtensionMemberId *) p2; + int cmpval; + + /* + * Compare OID first since it's usually unique, whereas there will only be + * a few distinct values of tableoid. + */ + cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid); + if (cmpval == 0) + cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid); + return cmpval; +} + + +/* + * findParentsByOid + * find a table's parents in tblinfo[] + */ +static void +findParentsByOid(TableInfo *self, + InhInfo *inhinfo, int numInherits) +{ + Oid oid = self->dobj.catId.oid; + int i, + j; + int numParents; + + numParents = 0; + for (i = 0; i < numInherits; i++) + { + if (inhinfo[i].inhrelid == oid) + numParents++; + } + + self->numParents = numParents; + + if (numParents > 0) + { + self->parents = (TableInfo **) + pg_malloc(sizeof(TableInfo *) * numParents); + j = 0; + for (i = 0; i < numInherits; i++) + { + if (inhinfo[i].inhrelid == oid) + { + TableInfo *parent; + + parent = findTableByOid(inhinfo[i].inhparent); + if (parent == NULL) + { + pg_log_error("failed sanity check, parent OID %u of table \"%s\" (OID %u) not found", + inhinfo[i].inhparent, + self->dobj.name, + oid); + exit_nicely(1); + } + self->parents[j++] = parent; + } + } + } + else + self->parents = NULL; +} + +/* + * parseOidArray + * parse a string of numbers delimited by spaces into a character array + * + * Note: actually this is used for both Oids and potentially-signed + * attribute numbers. This should cause no trouble, but we could split + * the function into two functions with different argument types if it does. + */ + +void +parseOidArray(const char *str, Oid *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) + { + pg_log_error("could not parse numeric array \"%s\": too many numbers", str); + exit_nicely(1); + } + temp[j] = '\0'; + array[argNum++] = atooid(temp); + j = 0; + } + if (s == '\0') + break; + } + else + { + if (!(isdigit((unsigned char) s) || s == '-') || + j >= sizeof(temp) - 1) + { + pg_log_error("could not parse numeric array \"%s\": invalid character in number", str); + exit_nicely(1); + } + temp[j++] = s; + } + } + + while (argNum < arraysize) + array[argNum++] = InvalidOid; +} + + +/* + * 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; +} diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c new file mode 100644 index 0000000..808df19 --- /dev/null +++ b/src/bin/pg_dump/compress_io.c @@ -0,0 +1,717 @@ +/*------------------------------------------------------------------------- + * + * compress_io.c + * Routines for archivers to write an uncompressed or compressed data + * stream. + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * This file includes two APIs for dealing with compressed data. The first + * provides more flexibility, using callbacks to read/write data from the + * underlying stream. The second API is a wrapper around fopen/gzopen and + * friends, providing an interface similar to those, but abstracts away + * the possible compression. Both APIs use libz for the compression, but + * the second API uses gzip headers, so the resulting files can be easily + * manipulated with the gzip utility. + * + * Compressor API + * -------------- + * + * The interface for writing to an archive consists of three functions: + * AllocateCompressor, WriteDataToArchive and EndCompressor. First you call + * AllocateCompressor, then write all the data by calling WriteDataToArchive + * as many times as needed, and finally EndCompressor. WriteDataToArchive + * and EndCompressor will call the WriteFunc that was provided to + * AllocateCompressor for each chunk of compressed data. + * + * The interface for reading an archive consists of just one function: + * ReadDataFromArchive. ReadDataFromArchive reads the whole compressed input + * stream, by repeatedly calling the given ReadFunc. ReadFunc returns the + * compressed data chunk at a time, and ReadDataFromArchive decompresses it + * and passes the decompressed data to ahwrite(), until ReadFunc returns 0 + * to signal EOF. + * + * The interface is the same for compressed and uncompressed streams. + * + * Compressed stream API + * ---------------------- + * + * The compressed stream API is a wrapper around the C standard fopen() and + * libz's gzopen() APIs. It allows you to use the same functions for + * compressed and uncompressed streams. cfopen_read() first tries to open + * the file with given name, and if it fails, it tries to open the same + * file with the .gz suffix. cfopen_write() opens a file for writing, an + * extra argument specifies if the file should be compressed, and adds the + * .gz suffix to the filename if so. This allows you to easily handle both + * compressed and uncompressed files. + * + * IDENTIFICATION + * src/bin/pg_dump/compress_io.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "compress_io.h" +#include "pg_backup_utils.h" + +/*---------------------- + * Compressor API + *---------------------- + */ + +/* typedef appears in compress_io.h */ +struct CompressorState +{ + CompressionAlgorithm comprAlg; + WriteFunc writeF; + +#ifdef HAVE_LIBZ + z_streamp zp; + char *zlibOut; + size_t zlibOutSize; +#endif +}; + +static void ParseCompressionOption(int compression, CompressionAlgorithm *alg, + int *level); + +/* Routines that support zlib compressed data I/O */ +#ifdef HAVE_LIBZ +static void InitCompressorZlib(CompressorState *cs, int level); +static void DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, + bool flush); +static void ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF); +static void WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, + const char *data, size_t dLen); +static void EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs); +#endif + +/* Routines that support uncompressed data I/O */ +static void ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF); +static void WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, + const char *data, size_t dLen); + +/* + * Interprets a numeric 'compression' value. The algorithm implied by the + * value (zlib or none at the moment), is returned in *alg, and the + * zlib compression level in *level. + */ +static void +ParseCompressionOption(int compression, CompressionAlgorithm *alg, int *level) +{ + if (compression == Z_DEFAULT_COMPRESSION || + (compression > 0 && compression <= 9)) + *alg = COMPR_ALG_LIBZ; + else if (compression == 0) + *alg = COMPR_ALG_NONE; + else + { + fatal("invalid compression code: %d", compression); + *alg = COMPR_ALG_NONE; /* keep compiler quiet */ + } + + /* The level is just the passed-in value. */ + if (level) + *level = compression; +} + +/* Public interface routines */ + +/* Allocate a new compressor */ +CompressorState * +AllocateCompressor(int compression, WriteFunc writeF) +{ + CompressorState *cs; + CompressionAlgorithm alg; + int level; + + ParseCompressionOption(compression, &alg, &level); + +#ifndef HAVE_LIBZ + if (alg == COMPR_ALG_LIBZ) + fatal("not built with zlib support"); +#endif + + cs = (CompressorState *) pg_malloc0(sizeof(CompressorState)); + cs->writeF = writeF; + cs->comprAlg = alg; + + /* + * Perform compression algorithm specific initialization. + */ +#ifdef HAVE_LIBZ + if (alg == COMPR_ALG_LIBZ) + InitCompressorZlib(cs, level); +#endif + + return cs; +} + +/* + * Read all compressed data from the input stream (via readF) and print it + * out with ahwrite(). + */ +void +ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF) +{ + CompressionAlgorithm alg; + + ParseCompressionOption(compression, &alg, NULL); + + if (alg == COMPR_ALG_NONE) + ReadDataFromArchiveNone(AH, readF); + if (alg == COMPR_ALG_LIBZ) + { +#ifdef HAVE_LIBZ + ReadDataFromArchiveZlib(AH, readF); +#else + fatal("not built with zlib support"); +#endif + } +} + +/* + * Compress and write data to the output stream (via writeF). + */ +void +WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, + const void *data, size_t dLen) +{ + switch (cs->comprAlg) + { + case COMPR_ALG_LIBZ: +#ifdef HAVE_LIBZ + WriteDataToArchiveZlib(AH, cs, data, dLen); +#else + fatal("not built with zlib support"); +#endif + break; + case COMPR_ALG_NONE: + WriteDataToArchiveNone(AH, cs, data, dLen); + break; + } +} + +/* + * Terminate compression library context and flush its buffers. + */ +void +EndCompressor(ArchiveHandle *AH, CompressorState *cs) +{ +#ifdef HAVE_LIBZ + if (cs->comprAlg == COMPR_ALG_LIBZ) + EndCompressorZlib(AH, cs); +#endif + free(cs); +} + +/* Private routines, specific to each compression method. */ + +#ifdef HAVE_LIBZ +/* + * Functions for zlib compressed output. + */ + +static void +InitCompressorZlib(CompressorState *cs, int level) +{ + z_streamp zp; + + zp = cs->zp = (z_streamp) pg_malloc(sizeof(z_stream)); + zp->zalloc = Z_NULL; + zp->zfree = Z_NULL; + zp->opaque = Z_NULL; + + /* + * zlibOutSize is the buffer size we tell zlib it can output to. We + * actually allocate one extra byte because some routines want to append a + * trailing zero byte to the zlib output. + */ + cs->zlibOut = (char *) pg_malloc(ZLIB_OUT_SIZE + 1); + cs->zlibOutSize = ZLIB_OUT_SIZE; + + if (deflateInit(zp, level) != Z_OK) + fatal("could not initialize compression library: %s", + zp->msg); + + /* Just be paranoid - maybe End is called after Start, with no Write */ + zp->next_out = (void *) cs->zlibOut; + zp->avail_out = cs->zlibOutSize; +} + +static void +EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs) +{ + z_streamp zp = cs->zp; + + zp->next_in = NULL; + zp->avail_in = 0; + + /* Flush any remaining data from zlib buffer */ + DeflateCompressorZlib(AH, cs, true); + + if (deflateEnd(zp) != Z_OK) + fatal("could not close compression stream: %s", zp->msg); + + free(cs->zlibOut); + free(cs->zp); +} + +static void +DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) +{ + z_streamp zp = cs->zp; + char *out = cs->zlibOut; + int res = Z_OK; + + while (cs->zp->avail_in != 0 || flush) + { + res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH); + if (res == Z_STREAM_ERROR) + fatal("could not compress data: %s", zp->msg); + if ((flush && (zp->avail_out < cs->zlibOutSize)) + || (zp->avail_out == 0) + || (zp->avail_in != 0) + ) + { + /* + * Extra paranoia: avoid zero-length chunks, since a zero length + * chunk is the EOF marker in the custom format. This should never + * happen but... + */ + if (zp->avail_out < cs->zlibOutSize) + { + /* + * Any write function should do its own error checking but to + * make sure we do a check here as well... + */ + size_t len = cs->zlibOutSize - zp->avail_out; + + cs->writeF(AH, out, len); + } + zp->next_out = (void *) out; + zp->avail_out = cs->zlibOutSize; + } + + if (res == Z_STREAM_END) + break; + } +} + +static void +WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, + const char *data, size_t dLen) +{ + cs->zp->next_in = (void *) unconstify(char *, data); + cs->zp->avail_in = dLen; + DeflateCompressorZlib(AH, cs, false); +} + +static void +ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF) +{ + z_streamp zp; + char *out; + int res = Z_OK; + size_t cnt; + char *buf; + size_t buflen; + + zp = (z_streamp) pg_malloc(sizeof(z_stream)); + zp->zalloc = Z_NULL; + zp->zfree = Z_NULL; + zp->opaque = Z_NULL; + + buf = pg_malloc(ZLIB_IN_SIZE); + buflen = ZLIB_IN_SIZE; + + out = pg_malloc(ZLIB_OUT_SIZE + 1); + + if (inflateInit(zp) != Z_OK) + fatal("could not initialize compression library: %s", + zp->msg); + + /* no minimal chunk size for zlib */ + while ((cnt = readF(AH, &buf, &buflen))) + { + zp->next_in = (void *) buf; + zp->avail_in = cnt; + + while (zp->avail_in > 0) + { + zp->next_out = (void *) out; + zp->avail_out = ZLIB_OUT_SIZE; + + res = inflate(zp, 0); + if (res != Z_OK && res != Z_STREAM_END) + fatal("could not uncompress data: %s", zp->msg); + + out[ZLIB_OUT_SIZE - zp->avail_out] = '\0'; + ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH); + } + } + + zp->next_in = NULL; + zp->avail_in = 0; + while (res != Z_STREAM_END) + { + zp->next_out = (void *) out; + zp->avail_out = ZLIB_OUT_SIZE; + res = inflate(zp, 0); + if (res != Z_OK && res != Z_STREAM_END) + fatal("could not uncompress data: %s", zp->msg); + + out[ZLIB_OUT_SIZE - zp->avail_out] = '\0'; + ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH); + } + + if (inflateEnd(zp) != Z_OK) + fatal("could not close compression library: %s", zp->msg); + + free(buf); + free(out); + free(zp); +} +#endif /* HAVE_LIBZ */ + + +/* + * Functions for uncompressed output. + */ + +static void +ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF) +{ + size_t cnt; + char *buf; + size_t buflen; + + buf = pg_malloc(ZLIB_OUT_SIZE); + buflen = ZLIB_OUT_SIZE; + + while ((cnt = readF(AH, &buf, &buflen))) + { + ahwrite(buf, 1, cnt, AH); + } + + free(buf); +} + +static void +WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, + const char *data, size_t dLen) +{ + cs->writeF(AH, data, dLen); +} + + +/*---------------------- + * Compressed stream API + *---------------------- + */ + +/* + * cfp represents an open stream, wrapping the underlying FILE or gzFile + * pointer. This is opaque to the callers. + */ +struct cfp +{ + FILE *uncompressedfp; +#ifdef HAVE_LIBZ + gzFile compressedfp; +#endif +}; + +#ifdef HAVE_LIBZ +static int hasSuffix(const char *filename, const char *suffix); +#endif + +/* free() without changing errno; useful in several places below */ +static void +free_keep_errno(void *p) +{ + int save_errno = errno; + + free(p); + errno = save_errno; +} + +/* + * Open a file for reading. 'path' is the file to open, and 'mode' should + * be either "r" or "rb". + * + * If the file at 'path' does not exist, we append the ".gz" suffix (if 'path' + * doesn't already have it) and try again. So if you pass "foo" as 'path', + * this will open either "foo" or "foo.gz". + * + * On failure, return NULL with an error code in errno. + */ +cfp * +cfopen_read(const char *path, const char *mode) +{ + cfp *fp; + +#ifdef HAVE_LIBZ + if (hasSuffix(path, ".gz")) + fp = cfopen(path, mode, 1); + else +#endif + { + fp = cfopen(path, mode, 0); +#ifdef HAVE_LIBZ + if (fp == NULL) + { + char *fname; + + fname = psprintf("%s.gz", path); + fp = cfopen(fname, mode, 1); + free_keep_errno(fname); + } +#endif + } + return fp; +} + +/* + * Open a file for writing. 'path' indicates the path name, and 'mode' must + * be a filemode as accepted by fopen() and gzopen() that indicates writing + * ("w", "wb", "a", or "ab"). + * + * If 'compression' is non-zero, a gzip compressed stream is opened, and + * 'compression' indicates the compression level used. The ".gz" suffix + * is automatically added to 'path' in that case. + * + * On failure, return NULL with an error code in errno. + */ +cfp * +cfopen_write(const char *path, const char *mode, int compression) +{ + cfp *fp; + + if (compression == 0) + fp = cfopen(path, mode, 0); + else + { +#ifdef HAVE_LIBZ + char *fname; + + fname = psprintf("%s.gz", path); + fp = cfopen(fname, mode, compression); + free_keep_errno(fname); +#else + fatal("not built with zlib support"); + fp = NULL; /* keep compiler quiet */ +#endif + } + return fp; +} + +/* + * Opens file 'path' in 'mode'. If 'compression' is non-zero, the file + * is opened with libz gzopen(), otherwise with plain fopen(). + * + * On failure, return NULL with an error code in errno. + */ +cfp * +cfopen(const char *path, const char *mode, int compression) +{ + cfp *fp = pg_malloc(sizeof(cfp)); + + if (compression != 0) + { +#ifdef HAVE_LIBZ + if (compression != Z_DEFAULT_COMPRESSION) + { + /* user has specified a compression level, so tell zlib to use it */ + char mode_compression[32]; + + snprintf(mode_compression, sizeof(mode_compression), "%s%d", + mode, compression); + fp->compressedfp = gzopen(path, mode_compression); + } + else + { + /* don't specify a level, just use the zlib default */ + fp->compressedfp = gzopen(path, mode); + } + + fp->uncompressedfp = NULL; + if (fp->compressedfp == NULL) + { + free_keep_errno(fp); + fp = NULL; + } +#else + fatal("not built with zlib support"); +#endif + } + else + { +#ifdef HAVE_LIBZ + fp->compressedfp = NULL; +#endif + fp->uncompressedfp = fopen(path, mode); + if (fp->uncompressedfp == NULL) + { + free_keep_errno(fp); + fp = NULL; + } + } + + return fp; +} + + +int +cfread(void *ptr, int size, cfp *fp) +{ + int ret; + + if (size == 0) + return 0; + +#ifdef HAVE_LIBZ + if (fp->compressedfp) + { + ret = gzread(fp->compressedfp, ptr, size); + if (ret != size && !gzeof(fp->compressedfp)) + { + int errnum; + const char *errmsg = gzerror(fp->compressedfp, &errnum); + + fatal("could not read from input file: %s", + errnum == Z_ERRNO ? strerror(errno) : errmsg); + } + } + else +#endif + { + ret = fread(ptr, 1, size, fp->uncompressedfp); + if (ret != size && !feof(fp->uncompressedfp)) + READ_ERROR_EXIT(fp->uncompressedfp); + } + return ret; +} + +int +cfwrite(const void *ptr, int size, cfp *fp) +{ +#ifdef HAVE_LIBZ + if (fp->compressedfp) + return gzwrite(fp->compressedfp, ptr, size); + else +#endif + return fwrite(ptr, 1, size, fp->uncompressedfp); +} + +int +cfgetc(cfp *fp) +{ + int ret; + +#ifdef HAVE_LIBZ + if (fp->compressedfp) + { + ret = gzgetc(fp->compressedfp); + if (ret == EOF) + { + if (!gzeof(fp->compressedfp)) + fatal("could not read from input file: %s", strerror(errno)); + else + fatal("could not read from input file: end of file"); + } + } + else +#endif + { + ret = fgetc(fp->uncompressedfp); + if (ret == EOF) + READ_ERROR_EXIT(fp->uncompressedfp); + } + + return ret; +} + +char * +cfgets(cfp *fp, char *buf, int len) +{ +#ifdef HAVE_LIBZ + if (fp->compressedfp) + return gzgets(fp->compressedfp, buf, len); + else +#endif + return fgets(buf, len, fp->uncompressedfp); +} + +int +cfclose(cfp *fp) +{ + int result; + + if (fp == NULL) + { + errno = EBADF; + return EOF; + } +#ifdef HAVE_LIBZ + if (fp->compressedfp) + { + result = gzclose(fp->compressedfp); + fp->compressedfp = NULL; + } + else +#endif + { + result = fclose(fp->uncompressedfp); + fp->uncompressedfp = NULL; + } + free_keep_errno(fp); + + return result; +} + +int +cfeof(cfp *fp) +{ +#ifdef HAVE_LIBZ + if (fp->compressedfp) + return gzeof(fp->compressedfp); + else +#endif + return feof(fp->uncompressedfp); +} + +const char * +get_cfp_error(cfp *fp) +{ +#ifdef HAVE_LIBZ + if (fp->compressedfp) + { + int errnum; + const char *errmsg = gzerror(fp->compressedfp, &errnum); + + if (errnum != Z_ERRNO) + return errmsg; + } +#endif + return strerror(errno); +} + +#ifdef HAVE_LIBZ +static int +hasSuffix(const char *filename, const char *suffix) +{ + int filenamelen = strlen(filename); + int suffixlen = strlen(suffix); + + if (filenamelen < suffixlen) + return 0; + + return memcmp(&filename[filenamelen - suffixlen], + suffix, + suffixlen) == 0; +} + +#endif diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h new file mode 100644 index 0000000..1eafbd8 --- /dev/null +++ b/src/bin/pg_dump/compress_io.h @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------- + * + * compress_io.h + * Interface to compress_io.c routines + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/pg_dump/compress_io.h + * + *------------------------------------------------------------------------- + */ + +#ifndef __COMPRESS_IO__ +#define __COMPRESS_IO__ + +#include "pg_backup_archiver.h" + +/* Initial buffer sizes used in zlib compression. */ +#define ZLIB_OUT_SIZE 4096 +#define ZLIB_IN_SIZE 4096 + +typedef enum +{ + COMPR_ALG_NONE, + COMPR_ALG_LIBZ +} CompressionAlgorithm; + +/* Prototype for callback function to WriteDataToArchive() */ +typedef void (*WriteFunc) (ArchiveHandle *AH, const char *buf, size_t len); + +/* + * Prototype for callback function to ReadDataFromArchive() + * + * ReadDataFromArchive will call the read function repeatedly, until it + * returns 0 to signal EOF. ReadDataFromArchive passes a buffer to read the + * data into in *buf, of length *buflen. If that's not big enough for the + * callback function, it can free() it and malloc() a new one, returning the + * new buffer and its size in *buf and *buflen. + * + * Returns the number of bytes read into *buf, or 0 on EOF. + */ +typedef size_t (*ReadFunc) (ArchiveHandle *AH, char **buf, size_t *buflen); + +/* struct definition appears in compress_io.c */ +typedef struct CompressorState CompressorState; + +extern CompressorState *AllocateCompressor(int compression, WriteFunc writeF); +extern void ReadDataFromArchive(ArchiveHandle *AH, int compression, + ReadFunc readF); +extern void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, + const void *data, size_t dLen); +extern void EndCompressor(ArchiveHandle *AH, CompressorState *cs); + + +typedef struct cfp cfp; + +extern cfp *cfopen(const char *path, const char *mode, int compression); +extern cfp *cfopen_read(const char *path, const char *mode); +extern cfp *cfopen_write(const char *path, const char *mode, int compression); +extern int cfread(void *ptr, int size, cfp *fp); +extern int cfwrite(const void *ptr, int size, cfp *fp); +extern int cfgetc(cfp *fp); +extern char *cfgets(cfp *fp, char *buf, int len); +extern int cfclose(cfp *fp); +extern int cfeof(cfp *fp); +extern const char *get_cfp_error(cfp *fp); + +#endif diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c new file mode 100644 index 0000000..60d306e --- /dev/null +++ b/src/bin/pg_dump/dumputils.c @@ -0,0 +1,1045 @@ +/*------------------------------------------------------------------------- + * + * Utility routines for SQL dumping + * + * Basically this is stuff that is useful in both pg_dump and pg_dumpall. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/dumputils.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include + +#include "dumputils.h" +#include "fe_utils/string_utils.h" + + +static bool parseAclItem(const char *item, const char *type, + const char *name, const char *subname, int remoteVersion, + PQExpBuffer grantee, PQExpBuffer grantor, + PQExpBuffer privs, PQExpBuffer privswgo); +static char *copyAclUserName(PQExpBuffer output, char *input); +static void AddAcl(PQExpBuffer aclbuf, const char *keyword, + const char *subname); + + +/* + * Build GRANT/REVOKE command(s) for an object. + * + * name: the object name, in the form to use in the commands (already quoted) + * subname: the sub-object name, if any (already quoted); NULL if none + * nspname: the namespace the object is in (NULL if none); not pre-quoted + * type: the object type (as seen in GRANT command: must be one of + * TABLE, SEQUENCE, FUNCTION, PROCEDURE, LANGUAGE, SCHEMA, DATABASE, TABLESPACE, + * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT) + * acls: the ACL string fetched from the database + * racls: the ACL string of any initial-but-now-revoked privileges + * owner: username of object owner (will be passed through fmtId); can be + * NULL or empty string to indicate "no owner known" + * prefix: string to prefix to each generated command; typically empty + * remoteVersion: version of database + * + * Returns true if okay, false if could not parse the acl string. + * The resulting commands (if any) are appended to the contents of 'sql'. + * + * Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES " + * or something similar, and name is an empty string. + * + * Note: beware of passing a fmtId() result directly as 'name' or 'subname', + * since this routine uses fmtId() internally. + */ +bool +buildACLCommands(const char *name, const char *subname, const char *nspname, + const char *type, const char *acls, const char *racls, + const char *owner, const char *prefix, int remoteVersion, + PQExpBuffer sql) +{ + bool ok = true; + char **aclitems = NULL; + char **raclitems = NULL; + int naclitems = 0; + int nraclitems = 0; + int i; + PQExpBuffer grantee, + grantor, + privs, + privswgo; + PQExpBuffer firstsql, + secondsql; + bool found_owner_privs = false; + + if (strlen(acls) == 0 && strlen(racls) == 0) + return true; /* object has default permissions */ + + /* treat empty-string owner same as NULL */ + if (owner && *owner == '\0') + owner = NULL; + + if (strlen(acls) != 0) + { + if (!parsePGArray(acls, &aclitems, &naclitems)) + { + if (aclitems) + free(aclitems); + return false; + } + } + + if (strlen(racls) != 0) + { + if (!parsePGArray(racls, &raclitems, &nraclitems)) + { + if (aclitems) + free(aclitems); + if (raclitems) + free(raclitems); + return false; + } + } + + grantee = createPQExpBuffer(); + grantor = createPQExpBuffer(); + privs = createPQExpBuffer(); + privswgo = createPQExpBuffer(); + + /* + * At the end, these two will be pasted together to form the result. + * + * For older systems we use these to ensure that the owner privileges go + * before the other ones, as a GRANT could create the default entry for + * the object, which generally includes all rights for the owner. In more + * recent versions we normally handle this because the owner rights come + * first in the ACLs, but older versions might have them after the PUBLIC + * privileges. + * + * For 9.6 and later systems, much of this changes. With 9.6, we check + * the default privileges for the objects at dump time and create two sets + * of ACLs- "racls" which are the ACLs to REVOKE from the object (as the + * object may have initial privileges on it, along with any default ACLs + * which are not part of the current set of privileges), and regular + * "acls", which are the ACLs to GRANT to the object. We handle the + * REVOKEs first, followed by the GRANTs. + */ + firstsql = createPQExpBuffer(); + secondsql = createPQExpBuffer(); + + /* + * For pre-9.6 systems, we always start with REVOKE ALL FROM PUBLIC, as we + * don't wish to make any assumptions about what the default ACLs are, and + * we do not collect them during the dump phase (and racls will always be + * the empty set, see above). + * + * For 9.6 and later, if any revoke ACLs have been provided, then include + * them in 'firstsql'. + * + * Revoke ACLs happen when an object starts out life with a set of + * privileges (eg: GRANT SELECT ON pg_class TO PUBLIC;) and the user has + * decided to revoke those rights. Since those objects come into being + * with those default privileges, we have to revoke them to match what the + * current state of affairs is. Note that we only started explicitly + * tracking such initial rights in 9.6, and prior to that all initial + * rights are actually handled by the simple 'REVOKE ALL .. FROM PUBLIC' + * case, for initdb-created objects. Prior to 9.6, we didn't handle + * extensions correctly, but we do now by tracking their initial + * privileges, in the same way we track initdb initial privileges, see + * pg_init_privs. + */ + if (remoteVersion < 90600) + { + Assert(nraclitems == 0); + + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s ", type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM PUBLIC;\n", name); + } + else + { + /* Scan individual REVOKE ACL items */ + for (i = 0; i < nraclitems; i++) + { + if (!parseAclItem(raclitems[i], type, name, subname, remoteVersion, + grantee, grantor, privs, NULL)) + { + ok = false; + break; + } + + if (privs->len > 0) + { + appendPQExpBuffer(firstsql, "%sREVOKE %s ON %s ", + prefix, privs->data, type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM ", name); + if (grantee->len == 0) + appendPQExpBufferStr(firstsql, "PUBLIC;\n"); + else if (strncmp(grantee->data, "group ", + strlen("group ")) == 0) + appendPQExpBuffer(firstsql, "GROUP %s;\n", + fmtId(grantee->data + strlen("group "))); + else + appendPQExpBuffer(firstsql, "%s;\n", + fmtId(grantee->data)); + } + } + } + + /* + * We still need some hacking though to cover the case where new default + * public privileges are added in new versions: the REVOKE ALL will revoke + * them, leading to behavior different from what the old version had, + * which is generally not what's wanted. So add back default privs if the + * source database is too old to have had that particular priv. + */ + if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0) + { + /* database CONNECT priv didn't exist before 8.2 */ + appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n", + prefix, type, name); + } + + /* Scan individual ACL items */ + for (i = 0; i < naclitems; i++) + { + if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion, + grantee, grantor, privs, privswgo)) + { + ok = false; + break; + } + + if (grantor->len == 0 && owner) + printfPQExpBuffer(grantor, "%s", owner); + + if (privs->len > 0 || privswgo->len > 0) + { + /* + * Prior to 9.6, we had to handle owner privileges in a special + * manner by first REVOKE'ing the rights and then GRANT'ing them + * after. With 9.6 and above, what we need to REVOKE and what we + * need to GRANT is figured out when we dump and stashed into + * "racls" and "acls", respectively. See above. + */ + if (remoteVersion < 90600 && owner + && strcmp(grantee->data, owner) == 0 + && strcmp(grantor->data, owner) == 0) + { + found_owner_privs = true; + + /* + * For the owner, the default privilege level is ALL WITH + * GRANT OPTION. + */ + if (strcmp(privswgo->data, "ALL") != 0) + { + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s ", type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM %s;\n", + name, fmtId(grantee->data)); + if (privs->len > 0) + { + appendPQExpBuffer(firstsql, + "%sGRANT %s ON %s ", + prefix, privs->data, type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, + "%s TO %s;\n", + name, fmtId(grantee->data)); + } + if (privswgo->len > 0) + { + appendPQExpBuffer(firstsql, + "%sGRANT %s ON %s ", + prefix, privswgo->data, type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, + "%s TO %s WITH GRANT OPTION;\n", + name, fmtId(grantee->data)); + } + } + } + else + { + /* + * For systems prior to 9.6, we can assume we are starting + * from no privs at this point. + * + * For 9.6 and above, at this point we have issued REVOKE + * statements for all initial and default privileges which are + * no longer present on the object (as they were passed in as + * 'racls') and we can simply GRANT the rights which are in + * 'acls'. + */ + if (grantor->len > 0 + && (!owner || strcmp(owner, grantor->data) != 0)) + appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n", + fmtId(grantor->data)); + + if (privs->len > 0) + { + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ", + prefix, privs->data, type); + if (nspname && *nspname) + appendPQExpBuffer(secondsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(secondsql, "%s TO ", name); + if (grantee->len == 0) + appendPQExpBufferStr(secondsql, "PUBLIC;\n"); + else if (strncmp(grantee->data, "group ", + strlen("group ")) == 0) + appendPQExpBuffer(secondsql, "GROUP %s;\n", + fmtId(grantee->data + strlen("group "))); + else + appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data)); + } + if (privswgo->len > 0) + { + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ", + prefix, privswgo->data, type); + if (nspname && *nspname) + appendPQExpBuffer(secondsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(secondsql, "%s TO ", name); + if (grantee->len == 0) + appendPQExpBufferStr(secondsql, "PUBLIC"); + else if (strncmp(grantee->data, "group ", + strlen("group ")) == 0) + appendPQExpBuffer(secondsql, "GROUP %s", + fmtId(grantee->data + strlen("group "))); + else + appendPQExpBufferStr(secondsql, fmtId(grantee->data)); + appendPQExpBufferStr(secondsql, " WITH GRANT OPTION;\n"); + } + + if (grantor->len > 0 + && (!owner || strcmp(owner, grantor->data) != 0)) + appendPQExpBufferStr(secondsql, "RESET SESSION AUTHORIZATION;\n"); + } + } + } + + /* + * For systems prior to 9.6, if we didn't find any owner privs, the owner + * must have revoked 'em all. + * + * For 9.6 and above, we handle this through the 'racls'. See above. + */ + if (remoteVersion < 90600 && !found_owner_privs && owner) + { + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s ", type); + if (nspname && *nspname) + appendPQExpBuffer(firstsql, "%s.", fmtId(nspname)); + appendPQExpBuffer(firstsql, "%s FROM %s;\n", + name, fmtId(owner)); + } + + destroyPQExpBuffer(grantee); + destroyPQExpBuffer(grantor); + destroyPQExpBuffer(privs); + destroyPQExpBuffer(privswgo); + + appendPQExpBuffer(sql, "%s%s", firstsql->data, secondsql->data); + destroyPQExpBuffer(firstsql); + destroyPQExpBuffer(secondsql); + + if (aclitems) + free(aclitems); + + if (raclitems) + free(raclitems); + + return ok; +} + +/* + * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry. + * + * type: the object type (TABLES, FUNCTIONS, etc) + * nspname: schema name, or NULL for global default privileges + * acls: the ACL string fetched from the database + * owner: username of privileges owner (will be passed through fmtId) + * remoteVersion: version of database + * + * Returns true if okay, false if could not parse the acl string. + * The resulting commands (if any) are appended to the contents of 'sql'. + */ +bool +buildDefaultACLCommands(const char *type, const char *nspname, + const char *acls, const char *racls, + const char *initacls, const char *initracls, + const char *owner, + int remoteVersion, + PQExpBuffer sql) +{ + PQExpBuffer prefix; + + prefix = createPQExpBuffer(); + + /* + * We incorporate the target role directly into the command, rather than + * playing around with SET ROLE or anything like that. This is so that a + * permissions error leads to nothing happening, rather than changing + * default privileges for the wrong user. + */ + appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ", + fmtId(owner)); + if (nspname) + appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname)); + + if (strlen(initacls) != 0 || strlen(initracls) != 0) + { + appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n"); + if (!buildACLCommands("", NULL, NULL, type, + initacls, initracls, owner, + prefix->data, remoteVersion, sql)) + { + destroyPQExpBuffer(prefix); + return false; + } + appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n"); + } + + if (!buildACLCommands("", NULL, NULL, type, + acls, racls, owner, + prefix->data, remoteVersion, sql)) + { + destroyPQExpBuffer(prefix); + return false; + } + + destroyPQExpBuffer(prefix); + + return true; +} + +/* + * This will parse an aclitem string, having the general form + * username=privilegecodes/grantor + * or + * group groupname=privilegecodes/grantor + * (the "group" case occurs only with servers before 8.1). + * + * Returns true on success, false on parse error. On success, the components + * of the string are returned in the PQExpBuffer parameters. + * + * The returned grantee string will be the dequoted username or groupname + * (preceded with "group " in the latter case). Note that a grant to PUBLIC + * is represented by an empty grantee string. The returned grantor is the + * dequoted grantor name. Privilege characters are translated to GRANT/REVOKE + * comma-separated privileges lists. If "privswgo" is non-NULL, the result is + * separate lists for privileges with grant option ("privswgo") and without + * ("privs"). Otherwise, "privs" bears every relevant privilege, ignoring the + * grant option distinction. + * + * Note: for cross-version compatibility, it's important to use ALL to + * represent the privilege sets whenever appropriate. + */ +static bool +parseAclItem(const char *item, const char *type, + const char *name, const char *subname, int remoteVersion, + PQExpBuffer grantee, PQExpBuffer grantor, + PQExpBuffer privs, PQExpBuffer privswgo) +{ + char *buf; + bool all_with_go = true; + bool all_without_go = true; + char *eqpos; + char *slpos; + char *pos; + + buf = pg_strdup(item); + + /* user or group name is string up to = */ + eqpos = copyAclUserName(grantee, buf); + if (*eqpos != '=') + { + pg_free(buf); + return false; + } + + /* grantor should appear after / */ + slpos = strchr(eqpos + 1, '/'); + if (slpos) + { + *slpos++ = '\0'; + slpos = copyAclUserName(grantor, slpos); + if (*slpos != '\0') + { + pg_free(buf); + return false; + } + } + else + { + pg_free(buf); + return false; + } + + /* privilege codes */ +#define CONVERT_PRIV(code, keywd) \ +do { \ + if ((pos = strchr(eqpos + 1, code))) \ + { \ + if (*(pos + 1) == '*' && privswgo != NULL) \ + { \ + AddAcl(privswgo, keywd, subname); \ + all_without_go = false; \ + } \ + else \ + { \ + AddAcl(privs, keywd, subname); \ + all_with_go = false; \ + } \ + } \ + else \ + all_with_go = all_without_go = false; \ +} while (0) + + resetPQExpBuffer(privs); + resetPQExpBuffer(privswgo); + + if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0) + { + CONVERT_PRIV('r', "SELECT"); + + if (strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "SEQUENCES") == 0) + /* sequence only */ + CONVERT_PRIV('U', "USAGE"); + else + { + /* table only */ + CONVERT_PRIV('a', "INSERT"); + CONVERT_PRIV('x', "REFERENCES"); + /* rest are not applicable to columns */ + if (subname == NULL) + { + CONVERT_PRIV('d', "DELETE"); + CONVERT_PRIV('t', "TRIGGER"); + if (remoteVersion >= 80400) + CONVERT_PRIV('D', "TRUNCATE"); + } + } + + /* UPDATE */ + CONVERT_PRIV('w', "UPDATE"); + } + else if (strcmp(type, "FUNCTION") == 0 || + strcmp(type, "FUNCTIONS") == 0) + CONVERT_PRIV('X', "EXECUTE"); + else if (strcmp(type, "PROCEDURE") == 0 || + strcmp(type, "PROCEDURES") == 0) + CONVERT_PRIV('X', "EXECUTE"); + else if (strcmp(type, "LANGUAGE") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "SCHEMA") == 0 || + strcmp(type, "SCHEMAS") == 0) + { + CONVERT_PRIV('C', "CREATE"); + CONVERT_PRIV('U', "USAGE"); + } + else if (strcmp(type, "DATABASE") == 0) + { + CONVERT_PRIV('C', "CREATE"); + CONVERT_PRIV('c', "CONNECT"); + CONVERT_PRIV('T', "TEMPORARY"); + } + else if (strcmp(type, "TABLESPACE") == 0) + CONVERT_PRIV('C', "CREATE"); + else if (strcmp(type, "TYPE") == 0 || + strcmp(type, "TYPES") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN SERVER") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN TABLE") == 0) + CONVERT_PRIV('r', "SELECT"); + else if (strcmp(type, "LARGE OBJECT") == 0) + { + CONVERT_PRIV('r', "SELECT"); + CONVERT_PRIV('w', "UPDATE"); + } + else + abort(); + +#undef CONVERT_PRIV + + if (all_with_go) + { + resetPQExpBuffer(privs); + printfPQExpBuffer(privswgo, "ALL"); + if (subname) + appendPQExpBuffer(privswgo, "(%s)", subname); + } + else if (all_without_go) + { + resetPQExpBuffer(privswgo); + printfPQExpBuffer(privs, "ALL"); + if (subname) + appendPQExpBuffer(privs, "(%s)", subname); + } + + pg_free(buf); + + return true; +} + +/* + * Transfer a user or group name starting at *input into the output buffer, + * dequoting if needed. Returns a pointer to just past the input name. + * The name is taken to end at an unquoted '=' or end of string. + */ +static char * +copyAclUserName(PQExpBuffer output, char *input) +{ + resetPQExpBuffer(output); + + while (*input && *input != '=') + { + /* + * If user name isn't quoted, then just add it to the output buffer + */ + if (*input != '"') + appendPQExpBufferChar(output, *input++); + else + { + /* Otherwise, it's a quoted username */ + input++; + /* Loop until we come across an unescaped quote */ + while (!(*input == '"' && *(input + 1) != '"')) + { + if (*input == '\0') + return input; /* really a syntax error... */ + + /* + * Quoting convention is to escape " as "". Keep this code in + * sync with putid() in backend's acl.c. + */ + if (*input == '"' && *(input + 1) == '"') + input++; + appendPQExpBufferChar(output, *input++); + } + input++; + } + } + return input; +} + +/* + * Append a privilege keyword to a keyword list, inserting comma if needed. + */ +static void +AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname) +{ + if (aclbuf->len > 0) + appendPQExpBufferChar(aclbuf, ','); + appendPQExpBufferStr(aclbuf, keyword); + if (subname) + appendPQExpBuffer(aclbuf, "(%s)", subname); +} + + +/* + * buildShSecLabelQuery + * + * Build a query to retrieve security labels for a shared object. + * The object is identified by its OID plus the name of the catalog + * it can be found in (e.g., "pg_database" for database names). + * The query is appended to "sql". (We don't execute it here so as to + * keep this file free of assumptions about how to deal with SQL errors.) + */ +void +buildShSecLabelQuery(const char *catalog_name, Oid objectId, + PQExpBuffer sql) +{ + appendPQExpBuffer(sql, + "SELECT provider, label FROM pg_catalog.pg_shseclabel " + "WHERE classoid = 'pg_catalog.%s'::pg_catalog.regclass " + "AND objoid = '%u'", catalog_name, objectId); +} + +/* + * emitShSecLabels + * + * Construct SECURITY LABEL commands using the data retrieved by the query + * generated by buildShSecLabelQuery, and append them to "buffer". + * Here, the target object is identified by its type name (e.g. "DATABASE") + * and its name (not pre-quoted). + */ +void +emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, + const char *objtype, const char *objname) +{ + int i; + + for (i = 0; i < PQntuples(res); i++) + { + char *provider = PQgetvalue(res, i, 0); + char *label = PQgetvalue(res, i, 1); + + /* must use fmtId result before calling it again */ + appendPQExpBuffer(buffer, + "SECURITY LABEL FOR %s ON %s", + fmtId(provider), objtype); + appendPQExpBuffer(buffer, + " %s IS ", + fmtId(objname)); + appendStringLiteralConn(buffer, label, conn); + appendPQExpBufferStr(buffer, ";\n"); + } +} + +/* + * buildACLQueries + * + * Build the subqueries to extract out the correct set of ACLs to be + * GRANT'd and REVOKE'd for the specific kind of object, accounting for any + * initial privileges (from pg_init_privs) and based on if we are in binary + * upgrade mode or not. + * + * Also builds subqueries to extract out the set of ACLs to go from the object + * default privileges to the privileges in pg_init_privs, if we are in binary + * upgrade mode, so that those privileges can be set up and recorded in the new + * cluster before the regular privileges are added on top of those. + */ +void +buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery, + PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery, + const char *acl_column, const char *acl_owner, + const char *obj_kind, bool binary_upgrade) +{ + /* + * To get the delta from what the permissions were at creation time + * (either initdb or CREATE EXTENSION) vs. what they are now, we have to + * look at two things: + * + * What privileges have been added, which we calculate by extracting all + * the current privileges (using the set of default privileges for the + * object type if current privileges are NULL) and then removing those + * which existed at creation time (again, using the set of default + * privileges for the object type if there were no creation time + * privileges). + * + * What privileges have been removed, which we calculate by extracting the + * privileges as they were at creation time (or the default privileges, as + * above), and then removing the current privileges (or the default + * privileges, if current privileges are NULL). + * + * As a good cross-check, both directions of these checks should result in + * the empty set if both the current ACL and the initial privs are NULL + * (meaning, in practice, that the default ACLs were there at init time + * and is what the current privileges are). + * + * We always perform this delta on all ACLs and expect that by the time + * these are run the initial privileges will be in place, even in a binary + * upgrade situation (see below). + * + * Finally, the order in which privileges are in the ACL string (the order + * they been GRANT'd in, which the backend maintains) must be preserved to + * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on + * those are dumped in the correct order. + */ + printfPQExpBuffer(acl_subquery, + "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM " + "(SELECT acl, row_n FROM " + "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) " + "WITH ORDINALITY AS perm(acl,row_n) " + "WHERE NOT EXISTS ( " + "SELECT 1 FROM " + "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) " + "AS init(init_acl) WHERE acl = init_acl)) as foo)", + acl_column, + obj_kind, + acl_owner, + obj_kind, + acl_owner); + + printfPQExpBuffer(racl_subquery, + "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM " + "(SELECT acl, row_n FROM " + "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) " + "WITH ORDINALITY AS initp(acl,row_n) " + "WHERE NOT EXISTS ( " + "SELECT 1 FROM " + "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) " + "AS permp(orig_acl) WHERE acl = orig_acl)) as foo)", + obj_kind, + acl_owner, + acl_column, + obj_kind, + acl_owner); + + /* + * In binary upgrade mode we don't run the extension script but instead + * dump out the objects independently and then recreate them. To preserve + * the initial privileges which were set on extension objects, we need to + * grab the set of GRANT and REVOKE commands necessary to get from the + * default privileges of an object to the initial privileges as recorded + * in pg_init_privs. + * + * These will then be run ahead of the regular ACL commands, which were + * calculated using the queries above, inside of a block which sets a flag + * to indicate that the backend should record the results of these GRANT + * and REVOKE statements into pg_init_privs. This is how we preserve the + * contents of that catalog across binary upgrades. + */ + if (binary_upgrade) + { + printfPQExpBuffer(init_acl_subquery, + "CASE WHEN privtype = 'e' THEN " + "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM " + "(SELECT acl, row_n FROM pg_catalog.unnest(pip.initprivs) " + "WITH ORDINALITY AS initp(acl,row_n) " + "WHERE NOT EXISTS ( " + "SELECT 1 FROM " + "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) " + "AS privm(orig_acl) WHERE acl = orig_acl)) as foo) END", + obj_kind, + acl_owner); + + printfPQExpBuffer(init_racl_subquery, + "CASE WHEN privtype = 'e' THEN " + "(SELECT pg_catalog.array_agg(acl) FROM " + "(SELECT acl, row_n FROM " + "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) " + "WITH ORDINALITY AS privp(acl,row_n) " + "WHERE NOT EXISTS ( " + "SELECT 1 FROM pg_catalog.unnest(pip.initprivs) " + "AS initp(init_acl) WHERE acl = init_acl)) as foo) END", + obj_kind, + acl_owner); + } + else + { + printfPQExpBuffer(init_acl_subquery, "NULL"); + printfPQExpBuffer(init_racl_subquery, "NULL"); + } +} + +/* + * Detect whether the given GUC variable is of GUC_LIST_QUOTE type. + * + * It'd be better if we could inquire this directly from the backend; but even + * if there were a function for that, it could only tell us about variables + * currently known to guc.c, so that it'd be unsafe for extensions to declare + * GUC_LIST_QUOTE variables anyway. Lacking a solution for that, it doesn't + * seem worth the work to do more than have this list, which must be kept in + * sync with the variables actually marked GUC_LIST_QUOTE in guc.c. + */ +bool +variable_is_guc_list_quote(const char *name) +{ + if (pg_strcasecmp(name, "local_preload_libraries") == 0 || + pg_strcasecmp(name, "search_path") == 0 || + pg_strcasecmp(name, "session_preload_libraries") == 0 || + pg_strcasecmp(name, "shared_preload_libraries") == 0 || + pg_strcasecmp(name, "temp_tablespaces") == 0 || + pg_strcasecmp(name, "unix_socket_directories") == 0) + return true; + else + return false; +} + +/* + * SplitGUCList --- parse a string containing identifiers or file names + * + * This is used to split the value of a GUC_LIST_QUOTE GUC variable, without + * presuming whether the elements will be taken as identifiers or file names. + * See comparable code in src/backend/utils/adt/varlena.c. + * + * Inputs: + * rawstring: the input string; must be overwritable! On return, it's + * been modified to contain the separated identifiers. + * separator: the separator punctuation expected between identifiers + * (typically '.' or ','). Whitespace may also appear around + * identifiers. + * Outputs: + * namelist: receives a malloc'd, null-terminated array of pointers to + * identifiers within rawstring. Caller should free this + * even on error return. + * + * Returns true if okay, false if there is a syntax error in the string. + */ +bool +SplitGUCList(char *rawstring, char separator, + char ***namelist) +{ + char *nextp = rawstring; + bool done = false; + char **nextptr; + + /* + * Since we disallow empty identifiers, this is a conservative + * overestimate of the number of pointers we could need. Allow one for + * list terminator. + */ + *namelist = nextptr = (char **) + pg_malloc((strlen(rawstring) / 2 + 2) * sizeof(char *)); + *nextptr = NULL; + + while (isspace((unsigned char) *nextp)) + nextp++; /* skip leading whitespace */ + + if (*nextp == '\0') + return true; /* allow empty string */ + + /* At the top of the loop, we are at start of a new identifier. */ + do + { + char *curname; + char *endp; + + if (*nextp == '"') + { + /* Quoted name --- collapse quote-quote pairs */ + curname = nextp + 1; + for (;;) + { + endp = strchr(nextp + 1, '"'); + if (endp == NULL) + return false; /* mismatched quotes */ + if (endp[1] != '"') + break; /* found end of quoted name */ + /* Collapse adjacent quotes into one quote, and look again */ + memmove(endp, endp + 1, strlen(endp)); + nextp = endp; + } + /* endp now points at the terminating quote */ + nextp = endp + 1; + } + else + { + /* Unquoted name --- extends to separator or whitespace */ + curname = nextp; + while (*nextp && *nextp != separator && + !isspace((unsigned char) *nextp)) + nextp++; + endp = nextp; + if (curname == nextp) + return false; /* empty unquoted name not allowed */ + } + + while (isspace((unsigned char) *nextp)) + nextp++; /* skip trailing whitespace */ + + if (*nextp == separator) + { + nextp++; + while (isspace((unsigned char) *nextp)) + nextp++; /* skip leading whitespace for next */ + /* we expect another name, so done remains false */ + } + else if (*nextp == '\0') + done = true; + else + return false; /* invalid syntax */ + + /* Now safe to overwrite separator with a null */ + *endp = '\0'; + + /* + * Finished isolating current name --- add it to output array + */ + *nextptr++ = curname; + + /* Loop back if we didn't reach end of string */ + } while (!done); + + *nextptr = NULL; + return true; +} + +/* + * Helper function for dumping "ALTER DATABASE/ROLE SET ..." commands. + * + * Parse the contents of configitem (a "name=value" string), wrap it in + * a complete ALTER command, and append it to buf. + * + * type is DATABASE or ROLE, and name is the name of the database or role. + * If we need an "IN" clause, type2 and name2 similarly define what to put + * there; otherwise they should be NULL. + * conn is used only to determine string-literal quoting conventions. + */ +void +makeAlterConfigCommand(PGconn *conn, const char *configitem, + const char *type, const char *name, + const char *type2, const char *name2, + PQExpBuffer buf) +{ + char *mine; + char *pos; + + /* Parse the configitem. If we can't find an "=", silently do nothing. */ + mine = pg_strdup(configitem); + pos = strchr(mine, '='); + if (pos == NULL) + { + pg_free(mine); + return; + } + *pos++ = '\0'; + + /* Build the command, with suitable quoting for everything. */ + appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name)); + if (type2 != NULL && name2 != NULL) + appendPQExpBuffer(buf, "IN %s %s ", type2, fmtId(name2)); + appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine)); + + /* + * Variables that are marked GUC_LIST_QUOTE were already fully quoted by + * flatten_set_variable_args() before they were put into the setconfig + * array. However, because the quoting rules used there aren't exactly + * like SQL's, we have to break the list value apart and then quote the + * elements as string literals. (The elements may be double-quoted as-is, + * but we can't just feed them to the SQL parser; it would do the wrong + * thing with elements that are zero-length or longer than NAMEDATALEN.) + * + * Variables that are not so marked should just be emitted as simple + * string literals. If the variable is not known to + * variable_is_guc_list_quote(), we'll do that; this makes it unsafe to + * use GUC_LIST_QUOTE for extension variables. + */ + if (variable_is_guc_list_quote(mine)) + { + char **namelist; + char **nameptr; + + /* Parse string into list of identifiers */ + /* this shouldn't fail really */ + if (SplitGUCList(pos, ',', &namelist)) + { + for (nameptr = namelist; *nameptr; nameptr++) + { + if (nameptr != namelist) + appendPQExpBufferStr(buf, ", "); + appendStringLiteralConn(buf, *nameptr, conn); + } + } + pg_free(namelist); + } + else + appendStringLiteralConn(buf, pos, conn); + + appendPQExpBufferStr(buf, ";\n"); + + pg_free(mine); +} diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h new file mode 100644 index 0000000..6e97da7 --- /dev/null +++ b/src/bin/pg_dump/dumputils.h @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------- + * + * Utility routines for SQL dumping + * + * Basically this is stuff that is useful in both pg_dump and pg_dumpall. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/dumputils.h + * + *------------------------------------------------------------------------- + */ +#ifndef DUMPUTILS_H +#define DUMPUTILS_H + +#include "libpq-fe.h" +#include "pqexpbuffer.h" + +/* + * Preferred strftime(3) format specifier for printing timestamps in pg_dump + * and friends. + * + * We don't print the timezone on Windows, because the names are long and + * localized, which means they may contain characters in various random + * encodings; this has been seen to cause encoding errors when reading the + * dump script. Think not to get around that by using %z, because + * (1) %z is not portable to pre-C99 systems, and + * (2) %z doesn't actually act differently from %Z on Windows anyway. + */ +#ifndef WIN32 +#define PGDUMP_STRFTIME_FMT "%Y-%m-%d %H:%M:%S %Z" +#else +#define PGDUMP_STRFTIME_FMT "%Y-%m-%d %H:%M:%S" +#endif + + +extern bool buildACLCommands(const char *name, const char *subname, const char *nspname, + const char *type, const char *acls, const char *racls, + const char *owner, const char *prefix, int remoteVersion, + PQExpBuffer sql); +extern bool buildDefaultACLCommands(const char *type, const char *nspname, + const char *acls, const char *racls, + const char *initacls, const char *initracls, + const char *owner, + int remoteVersion, + PQExpBuffer sql); +extern void buildShSecLabelQuery(const char *catalog_name, + Oid objectId, PQExpBuffer sql); +extern void emitShSecLabels(PGconn *conn, PGresult *res, + PQExpBuffer buffer, const char *objtype, const char *objname); + +extern void buildACLQueries(PQExpBuffer acl_subquery, PQExpBuffer racl_subquery, + PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery, + const char *acl_column, const char *acl_owner, + const char *obj_kind, bool binary_upgrade); + +extern bool variable_is_guc_list_quote(const char *name); + +extern bool SplitGUCList(char *rawstring, char separator, + char ***namelist); + +extern void makeAlterConfigCommand(PGconn *conn, const char *configitem, + const char *type, const char *name, + const char *type2, const char *name2, + PQExpBuffer buf); + +#endif /* DUMPUTILS_H */ diff --git a/src/bin/pg_dump/nls.mk b/src/bin/pg_dump/nls.mk new file mode 100644 index 0000000..4953b2a --- /dev/null +++ b/src/bin/pg_dump/nls.mk @@ -0,0 +1,18 @@ +# src/bin/pg_dump/nls.mk +CATALOG_NAME = pg_dump +AVAIL_LANGUAGES = cs de el es fr ja ko ru sv tr uk zh_CN +GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ + pg_backup_archiver.c pg_backup_db.c pg_backup_custom.c \ + pg_backup_null.c pg_backup_tar.c \ + pg_backup_directory.c dumputils.c compress_io.c \ + pg_dump.c common.c pg_dump_sort.c \ + pg_restore.c pg_dumpall.c \ + parallel.c parallel.h pg_backup_utils.c pg_backup_utils.h \ + ../../common/exec.c ../../common/fe_memutils.c \ + ../../common/wait_error.c +GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS) \ + fatal simple_prompt \ + ExecuteSqlCommand:3 warn_or_exit_horribly:2 +GETTEXT_FLAGS = $(FRONTEND_COMMON_GETTEXT_FLAGS) \ + fatal:1:c-format \ + warn_or_exit_horribly:2:c-format diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c new file mode 100644 index 0000000..f1577e7 --- /dev/null +++ b/src/bin/pg_dump/parallel.c @@ -0,0 +1,1806 @@ +/*------------------------------------------------------------------------- + * + * parallel.c + * + * Parallel support for pg_dump and pg_restore + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/pg_dump/parallel.c + * + *------------------------------------------------------------------------- + */ + +/* + * Parallel operation works like this: + * + * The original, leader process calls ParallelBackupStart(), which forks off + * the desired number of worker processes, which each enter WaitForCommands(). + * + * The leader process dispatches an individual work item to one of the worker + * processes in DispatchJobForTocEntry(). We send a command string such as + * "DUMP 1234" or "RESTORE 1234", where 1234 is the TocEntry ID. + * The worker process receives and decodes the command and passes it to the + * routine pointed to by AH->WorkerJobDumpPtr or AH->WorkerJobRestorePtr, + * which are routines of the current archive format. That routine performs + * the required action (dump or restore) and returns an integer status code. + * This is passed back to the leader where we pass it to the + * ParallelCompletionPtr callback function that was passed to + * DispatchJobForTocEntry(). The callback function does state updating + * for the leader control logic in pg_backup_archiver.c. + * + * In principle additional archive-format-specific information might be needed + * in commands or worker status responses, but so far that hasn't proved + * necessary, since workers have full copies of the ArchiveHandle/TocEntry + * data structures. Remember that we have forked off the workers only after + * we have read in the catalog. That's why our worker processes can also + * access the catalog information. (In the Windows case, the workers are + * threads in the same process. To avoid problems, they work with cloned + * copies of the Archive data structure; see RunWorker().) + * + * In the leader process, the workerStatus field for each worker has one of + * the following values: + * WRKR_NOT_STARTED: we've not yet forked this worker + * WRKR_IDLE: it's waiting for a command + * WRKR_WORKING: it's working on a command + * WRKR_TERMINATED: process ended + * The pstate->te[] entry for each worker is valid when it's in WRKR_WORKING + * state, and must be NULL in other states. + */ + +#include "postgres_fe.h" + +#ifndef WIN32 +#include +#include +#include +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "fe_utils/string_utils.h" +#include "parallel.h" +#include "pg_backup_utils.h" +#include "port/pg_bswap.h" + +/* Mnemonic macros for indexing the fd array returned by pipe(2) */ +#define PIPE_READ 0 +#define PIPE_WRITE 1 + +#define NO_SLOT (-1) /* Failure result for GetIdleWorker() */ + +/* Worker process statuses */ +typedef enum +{ + WRKR_NOT_STARTED = 0, + WRKR_IDLE, + WRKR_WORKING, + WRKR_TERMINATED +} T_WorkerStatus; + +#define WORKER_IS_RUNNING(workerStatus) \ + ((workerStatus) == WRKR_IDLE || (workerStatus) == WRKR_WORKING) + +/* + * Private per-parallel-worker state (typedef for this is in parallel.h). + * + * Much of this is valid only in the leader process (or, on Windows, should + * be touched only by the leader thread). But the AH field should be touched + * only by workers. The pipe descriptors are valid everywhere. + */ +struct ParallelSlot +{ + T_WorkerStatus workerStatus; /* see enum above */ + + /* These fields are valid if workerStatus == WRKR_WORKING: */ + ParallelCompletionPtr callback; /* function to call on completion */ + void *callback_data; /* passthrough data for it */ + + ArchiveHandle *AH; /* Archive data worker is using */ + + int pipeRead; /* leader's end of the pipes */ + int pipeWrite; + int pipeRevRead; /* child's end of the pipes */ + int pipeRevWrite; + + /* Child process/thread identity info: */ +#ifdef WIN32 + uintptr_t hThread; + unsigned int threadId; +#else + pid_t pid; +#endif +}; + +#ifdef WIN32 + +/* + * Structure to hold info passed by _beginthreadex() to the function it calls + * via its single allowed argument. + */ +typedef struct +{ + ArchiveHandle *AH; /* leader database connection */ + ParallelSlot *slot; /* this worker's parallel slot */ +} WorkerInfo; + +/* Windows implementation of pipe access */ +static int pgpipe(int handles[2]); +#define piperead(a,b,c) recv(a,b,c,0) +#define pipewrite(a,b,c) send(a,b,c,0) + +#else /* !WIN32 */ + +/* Non-Windows implementation of pipe access */ +#define pgpipe(a) pipe(a) +#define piperead(a,b,c) read(a,b,c) +#define pipewrite(a,b,c) write(a,b,c) + +#endif /* WIN32 */ + +/* + * State info for archive_close_connection() shutdown callback. + */ +typedef struct ShutdownInformation +{ + ParallelState *pstate; + Archive *AHX; +} ShutdownInformation; + +static ShutdownInformation shutdown_info; + +/* + * State info for signal handling. + * We assume signal_info initializes to zeroes. + * + * On Unix, myAH is the leader DB connection in the leader process, and the + * worker's own connection in worker processes. On Windows, we have only one + * instance of signal_info, so myAH is the leader connection and the worker + * connections must be dug out of pstate->parallelSlot[]. + */ +typedef struct DumpSignalInformation +{ + ArchiveHandle *myAH; /* database connection to issue cancel for */ + ParallelState *pstate; /* parallel state, if any */ + bool handler_set; /* signal handler set up in this process? */ +#ifndef WIN32 + bool am_worker; /* am I a worker process? */ +#endif +} DumpSignalInformation; + +static volatile DumpSignalInformation signal_info; + +#ifdef WIN32 +static CRITICAL_SECTION signal_info_lock; +#endif + +/* + * Write a simple string to stderr --- must be safe in a signal handler. + * We ignore the write() result since there's not much we could do about it. + * Certain compilers make that harder than it ought to be. + */ +#define write_stderr(str) \ + do { \ + const char *str_ = (str); \ + int rc_; \ + rc_ = write(fileno(stderr), str_, strlen(str_)); \ + (void) rc_; \ + } while (0) + + +#ifdef WIN32 +/* file-scope variables */ +static DWORD tls_index; + +/* globally visible variables (needed by exit_nicely) */ +bool parallel_init_done = false; +DWORD mainThreadId; +#endif /* WIN32 */ + +/* Local function prototypes */ +static ParallelSlot *GetMyPSlot(ParallelState *pstate); +static void archive_close_connection(int code, void *arg); +static void ShutdownWorkersHard(ParallelState *pstate); +static void WaitForTerminatingWorkers(ParallelState *pstate); +static void setup_cancel_handler(void); +static void set_cancel_pstate(ParallelState *pstate); +static void set_cancel_slot_archive(ParallelSlot *slot, ArchiveHandle *AH); +static void RunWorker(ArchiveHandle *AH, ParallelSlot *slot); +static int GetIdleWorker(ParallelState *pstate); +static bool HasEveryWorkerTerminated(ParallelState *pstate); +static void lockTableForWorker(ArchiveHandle *AH, TocEntry *te); +static void WaitForCommands(ArchiveHandle *AH, int pipefd[2]); +static bool ListenToWorkers(ArchiveHandle *AH, ParallelState *pstate, + bool do_wait); +static char *getMessageFromLeader(int pipefd[2]); +static void sendMessageToLeader(int pipefd[2], const char *str); +static int select_loop(int maxFd, fd_set *workerset); +static char *getMessageFromWorker(ParallelState *pstate, + bool do_wait, int *worker); +static void sendMessageToWorker(ParallelState *pstate, + int worker, const char *str); +static char *readMessageFromPipe(int fd); + +#define messageStartsWith(msg, prefix) \ + (strncmp(msg, prefix, strlen(prefix)) == 0) + + +/* + * Initialize parallel dump support --- should be called early in process + * startup. (Currently, this is called whether or not we intend parallel + * activity.) + */ +void +init_parallel_dump_utils(void) +{ +#ifdef WIN32 + if (!parallel_init_done) + { + WSADATA wsaData; + int err; + + /* Prepare for threaded operation */ + tls_index = TlsAlloc(); + mainThreadId = GetCurrentThreadId(); + + /* Initialize socket access */ + err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err != 0) + { + pg_log_error("%s() failed: error code %d", "WSAStartup", err); + exit_nicely(1); + } + + parallel_init_done = true; + } +#endif +} + +/* + * Find the ParallelSlot for the current worker process or thread. + * + * Returns NULL if no matching slot is found (this implies we're the leader). + */ +static ParallelSlot * +GetMyPSlot(ParallelState *pstate) +{ + int i; + + for (i = 0; i < pstate->numWorkers; i++) + { +#ifdef WIN32 + if (pstate->parallelSlot[i].threadId == GetCurrentThreadId()) +#else + if (pstate->parallelSlot[i].pid == getpid()) +#endif + return &(pstate->parallelSlot[i]); + } + + return NULL; +} + +/* + * A thread-local version of getLocalPQExpBuffer(). + * + * Non-reentrant but reduces memory leakage: we'll consume one buffer per + * thread, which is much better than one per fmtId/fmtQualifiedId call. + */ +#ifdef WIN32 +static PQExpBuffer +getThreadLocalPQExpBuffer(void) +{ + /* + * The Tls code goes awry if we use a static var, so we provide for both + * static and auto, and omit any use of the static var when using Tls. We + * rely on TlsGetValue() to return 0 if the value is not yet set. + */ + static PQExpBuffer s_id_return = NULL; + PQExpBuffer id_return; + + if (parallel_init_done) + id_return = (PQExpBuffer) TlsGetValue(tls_index); + else + id_return = s_id_return; + + if (id_return) /* first time through? */ + { + /* same buffer, just wipe contents */ + resetPQExpBuffer(id_return); + } + else + { + /* new buffer */ + id_return = createPQExpBuffer(); + if (parallel_init_done) + TlsSetValue(tls_index, id_return); + else + s_id_return = id_return; + } + + return id_return; +} +#endif /* WIN32 */ + +/* + * pg_dump and pg_restore call this to register the cleanup handler + * as soon as they've created the ArchiveHandle. + */ +void +on_exit_close_archive(Archive *AHX) +{ + shutdown_info.AHX = AHX; + on_exit_nicely(archive_close_connection, &shutdown_info); +} + +/* + * on_exit_nicely handler for shutting down database connections and + * worker processes cleanly. + */ +static void +archive_close_connection(int code, void *arg) +{ + ShutdownInformation *si = (ShutdownInformation *) arg; + + if (si->pstate) + { + /* In parallel mode, must figure out who we are */ + ParallelSlot *slot = GetMyPSlot(si->pstate); + + if (!slot) + { + /* + * We're the leader. Forcibly shut down workers, then close our + * own database connection, if any. + */ + ShutdownWorkersHard(si->pstate); + + if (si->AHX) + DisconnectDatabase(si->AHX); + } + else + { + /* + * We're a worker. Shut down our own DB connection if any. On + * Windows, we also have to close our communication sockets, to + * emulate what will happen on Unix when the worker process exits. + * (Without this, if this is a premature exit, the leader would + * fail to detect it because there would be no EOF condition on + * the other end of the pipe.) + */ + if (slot->AH) + DisconnectDatabase(&(slot->AH->public)); + +#ifdef WIN32 + closesocket(slot->pipeRevRead); + closesocket(slot->pipeRevWrite); +#endif + } + } + else + { + /* Non-parallel operation: just kill the leader DB connection */ + if (si->AHX) + DisconnectDatabase(si->AHX); + } +} + +/* + * Forcibly shut down any remaining workers, waiting for them to finish. + * + * Note that we don't expect to come here during normal exit (the workers + * should be long gone, and the ParallelState too). We're only here in a + * fatal() situation, so intervening to cancel active commands is + * appropriate. + */ +static void +ShutdownWorkersHard(ParallelState *pstate) +{ + int i; + + /* + * Close our write end of the sockets so that any workers waiting for + * commands know they can exit. (Note: some of the pipeWrite fields might + * still be zero, if we failed to initialize all the workers. Hence, just + * ignore errors here.) + */ + for (i = 0; i < pstate->numWorkers; i++) + closesocket(pstate->parallelSlot[i].pipeWrite); + + /* + * Force early termination of any commands currently in progress. + */ +#ifndef WIN32 + /* On non-Windows, send SIGTERM to each worker process. */ + for (i = 0; i < pstate->numWorkers; i++) + { + pid_t pid = pstate->parallelSlot[i].pid; + + if (pid != 0) + kill(pid, SIGTERM); + } +#else + + /* + * On Windows, send query cancels directly to the workers' backends. Use + * a critical section to ensure worker threads don't change state. + */ + EnterCriticalSection(&signal_info_lock); + for (i = 0; i < pstate->numWorkers; i++) + { + ArchiveHandle *AH = pstate->parallelSlot[i].AH; + char errbuf[1]; + + if (AH != NULL && AH->connCancel != NULL) + (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf)); + } + LeaveCriticalSection(&signal_info_lock); +#endif + + /* Now wait for them to terminate. */ + WaitForTerminatingWorkers(pstate); +} + +/* + * Wait for all workers to terminate. + */ +static void +WaitForTerminatingWorkers(ParallelState *pstate) +{ + while (!HasEveryWorkerTerminated(pstate)) + { + ParallelSlot *slot = NULL; + int j; + +#ifndef WIN32 + /* On non-Windows, use wait() to wait for next worker to end */ + int status; + pid_t pid = wait(&status); + + /* Find dead worker's slot, and clear the PID field */ + for (j = 0; j < pstate->numWorkers; j++) + { + slot = &(pstate->parallelSlot[j]); + if (slot->pid == pid) + { + slot->pid = 0; + break; + } + } +#else /* WIN32 */ + /* On Windows, we must use WaitForMultipleObjects() */ + HANDLE *lpHandles = pg_malloc(sizeof(HANDLE) * pstate->numWorkers); + int nrun = 0; + DWORD ret; + uintptr_t hThread; + + for (j = 0; j < pstate->numWorkers; j++) + { + if (WORKER_IS_RUNNING(pstate->parallelSlot[j].workerStatus)) + { + lpHandles[nrun] = (HANDLE) pstate->parallelSlot[j].hThread; + nrun++; + } + } + ret = WaitForMultipleObjects(nrun, lpHandles, false, INFINITE); + Assert(ret != WAIT_FAILED); + hThread = (uintptr_t) lpHandles[ret - WAIT_OBJECT_0]; + free(lpHandles); + + /* Find dead worker's slot, and clear the hThread field */ + for (j = 0; j < pstate->numWorkers; j++) + { + slot = &(pstate->parallelSlot[j]); + if (slot->hThread == hThread) + { + /* For cleanliness, close handles for dead threads */ + CloseHandle((HANDLE) slot->hThread); + slot->hThread = (uintptr_t) INVALID_HANDLE_VALUE; + break; + } + } +#endif /* WIN32 */ + + /* On all platforms, update workerStatus and te[] as well */ + Assert(j < pstate->numWorkers); + slot->workerStatus = WRKR_TERMINATED; + pstate->te[j] = NULL; + } +} + + +/* + * Code for responding to cancel interrupts (SIGINT, control-C, etc) + * + * This doesn't quite belong in this module, but it needs access to the + * ParallelState data, so there's not really a better place either. + * + * When we get a cancel interrupt, we could just die, but in pg_restore that + * could leave a SQL command (e.g., CREATE INDEX on a large table) running + * for a long time. Instead, we try to send a cancel request and then die. + * pg_dump probably doesn't really need this, but we might as well use it + * there too. Note that sending the cancel directly from the signal handler + * is safe because PQcancel() is written to make it so. + * + * In parallel operation on Unix, each process is responsible for canceling + * its own connection (this must be so because nobody else has access to it). + * Furthermore, the leader process should attempt to forward its signal to + * each child. In simple manual use of pg_dump/pg_restore, forwarding isn't + * needed because typing control-C at the console would deliver SIGINT to + * every member of the terminal process group --- but in other scenarios it + * might be that only the leader gets signaled. + * + * On Windows, the cancel handler runs in a separate thread, because that's + * how SetConsoleCtrlHandler works. We make it stop worker threads, send + * cancels on all active connections, and then return FALSE, which will allow + * the process to die. For safety's sake, we use a critical section to + * protect the PGcancel structures against being changed while the signal + * thread runs. + */ + +#ifndef WIN32 + +/* + * Signal handler (Unix only) + */ +static void +sigTermHandler(SIGNAL_ARGS) +{ + int i; + char errbuf[1]; + + /* + * Some platforms allow delivery of new signals to interrupt an active + * signal handler. That could muck up our attempt to send PQcancel, so + * disable the signals that setup_cancel_handler enabled. + */ + pqsignal(SIGINT, SIG_IGN); + pqsignal(SIGTERM, SIG_IGN); + pqsignal(SIGQUIT, SIG_IGN); + + /* + * If we're in the leader, forward signal to all workers. (It seems best + * to do this before PQcancel; killing the leader transaction will result + * in invalid-snapshot errors from active workers, which maybe we can + * quiet by killing workers first.) Ignore any errors. + */ + if (signal_info.pstate != NULL) + { + for (i = 0; i < signal_info.pstate->numWorkers; i++) + { + pid_t pid = signal_info.pstate->parallelSlot[i].pid; + + if (pid != 0) + kill(pid, SIGTERM); + } + } + + /* + * Send QueryCancel if we have a connection to send to. Ignore errors, + * there's not much we can do about them anyway. + */ + if (signal_info.myAH != NULL && signal_info.myAH->connCancel != NULL) + (void) PQcancel(signal_info.myAH->connCancel, errbuf, sizeof(errbuf)); + + /* + * Report we're quitting, using nothing more complicated than write(2). + * When in parallel operation, only the leader process should do this. + */ + if (!signal_info.am_worker) + { + if (progname) + { + write_stderr(progname); + write_stderr(": "); + } + write_stderr("terminated by user\n"); + } + + /* + * And die, using _exit() not exit() because the latter will invoke atexit + * handlers that can fail if we interrupted related code. + */ + _exit(1); +} + +/* + * Enable cancel interrupt handler, if not already done. + */ +static void +setup_cancel_handler(void) +{ + /* + * When forking, signal_info.handler_set will propagate into the new + * process, but that's fine because the signal handler state does too. + */ + if (!signal_info.handler_set) + { + signal_info.handler_set = true; + + pqsignal(SIGINT, sigTermHandler); + pqsignal(SIGTERM, sigTermHandler); + pqsignal(SIGQUIT, sigTermHandler); + } +} + +#else /* WIN32 */ + +/* + * Console interrupt handler --- runs in a newly-started thread. + * + * After stopping other threads and sending cancel requests on all open + * connections, we return FALSE which will allow the default ExitProcess() + * action to be taken. + */ +static BOOL WINAPI +consoleHandler(DWORD dwCtrlType) +{ + int i; + char errbuf[1]; + + if (dwCtrlType == CTRL_C_EVENT || + dwCtrlType == CTRL_BREAK_EVENT) + { + /* Critical section prevents changing data we look at here */ + EnterCriticalSection(&signal_info_lock); + + /* + * If in parallel mode, stop worker threads and send QueryCancel to + * their connected backends. The main point of stopping the worker + * threads is to keep them from reporting the query cancels as errors, + * which would clutter the user's screen. We needn't stop the leader + * thread since it won't be doing much anyway. Do this before + * canceling the main transaction, else we might get invalid-snapshot + * errors reported before we can stop the workers. Ignore errors, + * there's not much we can do about them anyway. + */ + if (signal_info.pstate != NULL) + { + for (i = 0; i < signal_info.pstate->numWorkers; i++) + { + ParallelSlot *slot = &(signal_info.pstate->parallelSlot[i]); + ArchiveHandle *AH = slot->AH; + HANDLE hThread = (HANDLE) slot->hThread; + + /* + * Using TerminateThread here may leave some resources leaked, + * but it doesn't matter since we're about to end the whole + * process. + */ + if (hThread != INVALID_HANDLE_VALUE) + TerminateThread(hThread, 0); + + if (AH != NULL && AH->connCancel != NULL) + (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf)); + } + } + + /* + * Send QueryCancel to leader connection, if enabled. Ignore errors, + * there's not much we can do about them anyway. + */ + if (signal_info.myAH != NULL && signal_info.myAH->connCancel != NULL) + (void) PQcancel(signal_info.myAH->connCancel, + errbuf, sizeof(errbuf)); + + LeaveCriticalSection(&signal_info_lock); + + /* + * Report we're quitting, using nothing more complicated than + * write(2). (We might be able to get away with using pg_log_*() + * here, but since we terminated other threads uncleanly above, it + * seems better to assume as little as possible.) + */ + if (progname) + { + write_stderr(progname); + write_stderr(": "); + } + write_stderr("terminated by user\n"); + } + + /* Always return FALSE to allow signal handling to continue */ + return FALSE; +} + +/* + * Enable cancel interrupt handler, if not already done. + */ +static void +setup_cancel_handler(void) +{ + if (!signal_info.handler_set) + { + signal_info.handler_set = true; + + InitializeCriticalSection(&signal_info_lock); + + SetConsoleCtrlHandler(consoleHandler, TRUE); + } +} + +#endif /* WIN32 */ + + +/* + * set_archive_cancel_info + * + * Fill AH->connCancel with cancellation info for the specified database + * connection; or clear it if conn is NULL. + */ +void +set_archive_cancel_info(ArchiveHandle *AH, PGconn *conn) +{ + PGcancel *oldConnCancel; + + /* + * Activate the interrupt handler if we didn't yet in this process. On + * Windows, this also initializes signal_info_lock; therefore it's + * important that this happen at least once before we fork off any + * threads. + */ + setup_cancel_handler(); + + /* + * On Unix, we assume that storing a pointer value is atomic with respect + * to any possible signal interrupt. On Windows, use a critical section. + */ + +#ifdef WIN32 + EnterCriticalSection(&signal_info_lock); +#endif + + /* Free the old one if we have one */ + oldConnCancel = AH->connCancel; + /* be sure interrupt handler doesn't use pointer while freeing */ + AH->connCancel = NULL; + + if (oldConnCancel != NULL) + PQfreeCancel(oldConnCancel); + + /* Set the new one if specified */ + if (conn) + AH->connCancel = PQgetCancel(conn); + + /* + * On Unix, there's only ever one active ArchiveHandle per process, so we + * can just set signal_info.myAH unconditionally. On Windows, do that + * only in the main thread; worker threads have to make sure their + * ArchiveHandle appears in the pstate data, which is dealt with in + * RunWorker(). + */ +#ifndef WIN32 + signal_info.myAH = AH; +#else + if (mainThreadId == GetCurrentThreadId()) + signal_info.myAH = AH; +#endif + +#ifdef WIN32 + LeaveCriticalSection(&signal_info_lock); +#endif +} + +/* + * set_cancel_pstate + * + * Set signal_info.pstate to point to the specified ParallelState, if any. + * We need this mainly to have an interlock against Windows signal thread. + */ +static void +set_cancel_pstate(ParallelState *pstate) +{ +#ifdef WIN32 + EnterCriticalSection(&signal_info_lock); +#endif + + signal_info.pstate = pstate; + +#ifdef WIN32 + LeaveCriticalSection(&signal_info_lock); +#endif +} + +/* + * set_cancel_slot_archive + * + * Set ParallelSlot's AH field to point to the specified archive, if any. + * We need this mainly to have an interlock against Windows signal thread. + */ +static void +set_cancel_slot_archive(ParallelSlot *slot, ArchiveHandle *AH) +{ +#ifdef WIN32 + EnterCriticalSection(&signal_info_lock); +#endif + + slot->AH = AH; + +#ifdef WIN32 + LeaveCriticalSection(&signal_info_lock); +#endif +} + + +/* + * This function is called by both Unix and Windows variants to set up + * and run a worker process. Caller should exit the process (or thread) + * upon return. + */ +static void +RunWorker(ArchiveHandle *AH, ParallelSlot *slot) +{ + int pipefd[2]; + + /* fetch child ends of pipes */ + pipefd[PIPE_READ] = slot->pipeRevRead; + pipefd[PIPE_WRITE] = slot->pipeRevWrite; + + /* + * Clone the archive so that we have our own state to work with, and in + * particular our own database connection. + * + * We clone on Unix as well as Windows, even though technically we don't + * need to because fork() gives us a copy in our own address space + * already. But CloneArchive resets the state information and also clones + * the database connection which both seem kinda helpful. + */ + AH = CloneArchive(AH); + + /* Remember cloned archive where signal handler can find it */ + set_cancel_slot_archive(slot, AH); + + /* + * Call the setup worker function that's defined in the ArchiveHandle. + */ + (AH->SetupWorkerPtr) ((Archive *) AH); + + /* + * Execute commands until done. + */ + WaitForCommands(AH, pipefd); + + /* + * Disconnect from database and clean up. + */ + set_cancel_slot_archive(slot, NULL); + DisconnectDatabase(&(AH->public)); + DeCloneArchive(AH); +} + +/* + * Thread base function for Windows + */ +#ifdef WIN32 +static unsigned __stdcall +init_spawned_worker_win32(WorkerInfo *wi) +{ + ArchiveHandle *AH = wi->AH; + ParallelSlot *slot = wi->slot; + + /* Don't need WorkerInfo anymore */ + free(wi); + + /* Run the worker ... */ + RunWorker(AH, slot); + + /* Exit the thread */ + _endthreadex(0); + return 0; +} +#endif /* WIN32 */ + +/* + * This function starts a parallel dump or restore by spawning off the worker + * processes. For Windows, it creates a number of threads; on Unix the + * workers are created with fork(). + */ +ParallelState * +ParallelBackupStart(ArchiveHandle *AH) +{ + ParallelState *pstate; + int i; + + Assert(AH->public.numWorkers > 0); + + pstate = (ParallelState *) pg_malloc(sizeof(ParallelState)); + + pstate->numWorkers = AH->public.numWorkers; + pstate->te = NULL; + pstate->parallelSlot = NULL; + + if (AH->public.numWorkers == 1) + return pstate; + + /* Create status arrays, being sure to initialize all fields to 0 */ + pstate->te = (TocEntry **) + pg_malloc0(pstate->numWorkers * sizeof(TocEntry *)); + pstate->parallelSlot = (ParallelSlot *) + pg_malloc0(pstate->numWorkers * sizeof(ParallelSlot)); + +#ifdef WIN32 + /* Make fmtId() and fmtQualifiedId() use thread-local storage */ + getLocalPQExpBuffer = getThreadLocalPQExpBuffer; +#endif + + /* + * Set the pstate in shutdown_info, to tell the exit handler that it must + * clean up workers as well as the main database connection. But we don't + * set this in signal_info yet, because we don't want child processes to + * inherit non-NULL signal_info.pstate. + */ + shutdown_info.pstate = pstate; + + /* + * Temporarily disable query cancellation on the leader connection. This + * ensures that child processes won't inherit valid AH->connCancel + * settings and thus won't try to issue cancels against the leader's + * connection. No harm is done if we fail while it's disabled, because + * the leader connection is idle at this point anyway. + */ + set_archive_cancel_info(AH, NULL); + + /* Ensure stdio state is quiesced before forking */ + fflush(NULL); + + /* Create desired number of workers */ + for (i = 0; i < pstate->numWorkers; i++) + { +#ifdef WIN32 + WorkerInfo *wi; + uintptr_t handle; +#else + pid_t pid; +#endif + ParallelSlot *slot = &(pstate->parallelSlot[i]); + int pipeMW[2], + pipeWM[2]; + + /* Create communication pipes for this worker */ + if (pgpipe(pipeMW) < 0 || pgpipe(pipeWM) < 0) + fatal("could not create communication channels: %m"); + + /* leader's ends of the pipes */ + slot->pipeRead = pipeWM[PIPE_READ]; + slot->pipeWrite = pipeMW[PIPE_WRITE]; + /* child's ends of the pipes */ + slot->pipeRevRead = pipeMW[PIPE_READ]; + slot->pipeRevWrite = pipeWM[PIPE_WRITE]; + +#ifdef WIN32 + /* Create transient structure to pass args to worker function */ + wi = (WorkerInfo *) pg_malloc(sizeof(WorkerInfo)); + + wi->AH = AH; + wi->slot = slot; + + handle = _beginthreadex(NULL, 0, (void *) &init_spawned_worker_win32, + wi, 0, &(slot->threadId)); + slot->hThread = handle; + slot->workerStatus = WRKR_IDLE; +#else /* !WIN32 */ + pid = fork(); + if (pid == 0) + { + /* we are the worker */ + int j; + + /* this is needed for GetMyPSlot() */ + slot->pid = getpid(); + + /* instruct signal handler that we're in a worker now */ + signal_info.am_worker = true; + + /* close read end of Worker -> Leader */ + closesocket(pipeWM[PIPE_READ]); + /* close write end of Leader -> Worker */ + closesocket(pipeMW[PIPE_WRITE]); + + /* + * Close all inherited fds for communication of the leader with + * previously-forked workers. + */ + for (j = 0; j < i; j++) + { + closesocket(pstate->parallelSlot[j].pipeRead); + closesocket(pstate->parallelSlot[j].pipeWrite); + } + + /* Run the worker ... */ + RunWorker(AH, slot); + + /* We can just exit(0) when done */ + exit(0); + } + else if (pid < 0) + { + /* fork failed */ + fatal("could not create worker process: %m"); + } + + /* In Leader after successful fork */ + slot->pid = pid; + slot->workerStatus = WRKR_IDLE; + + /* close read end of Leader -> Worker */ + closesocket(pipeMW[PIPE_READ]); + /* close write end of Worker -> Leader */ + closesocket(pipeWM[PIPE_WRITE]); +#endif /* WIN32 */ + } + + /* + * Having forked off the workers, disable SIGPIPE so that leader isn't + * killed if it tries to send a command to a dead worker. We don't want + * the workers to inherit this setting, though. + */ +#ifndef WIN32 + pqsignal(SIGPIPE, SIG_IGN); +#endif + + /* + * Re-establish query cancellation on the leader connection. + */ + set_archive_cancel_info(AH, AH->connection); + + /* + * Tell the cancel signal handler to forward signals to worker processes, + * too. (As with query cancel, we did not need this earlier because the + * workers have not yet been given anything to do; if we die before this + * point, any already-started workers will see EOF and quit promptly.) + */ + set_cancel_pstate(pstate); + + return pstate; +} + +/* + * Close down a parallel dump or restore. + */ +void +ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate) +{ + int i; + + /* No work if non-parallel */ + if (pstate->numWorkers == 1) + return; + + /* There should not be any unfinished jobs */ + Assert(IsEveryWorkerIdle(pstate)); + + /* Close the sockets so that the workers know they can exit */ + for (i = 0; i < pstate->numWorkers; i++) + { + closesocket(pstate->parallelSlot[i].pipeRead); + closesocket(pstate->parallelSlot[i].pipeWrite); + } + + /* Wait for them to exit */ + WaitForTerminatingWorkers(pstate); + + /* + * Unlink pstate from shutdown_info, so the exit handler will not try to + * use it; and likewise unlink from signal_info. + */ + shutdown_info.pstate = NULL; + set_cancel_pstate(NULL); + + /* Release state (mere neatnik-ism, since we're about to terminate) */ + free(pstate->te); + free(pstate->parallelSlot); + free(pstate); +} + +/* + * These next four functions handle construction and parsing of the command + * strings and response strings for parallel workers. + * + * Currently, these can be the same regardless of which archive format we are + * processing. In future, we might want to let format modules override these + * functions to add format-specific data to a command or response. + */ + +/* + * buildWorkerCommand: format a command string to send to a worker. + * + * The string is built in the caller-supplied buffer of size buflen. + */ +static void +buildWorkerCommand(ArchiveHandle *AH, TocEntry *te, T_Action act, + char *buf, int buflen) +{ + if (act == ACT_DUMP) + snprintf(buf, buflen, "DUMP %d", te->dumpId); + else if (act == ACT_RESTORE) + snprintf(buf, buflen, "RESTORE %d", te->dumpId); + else + Assert(false); +} + +/* + * parseWorkerCommand: interpret a command string in a worker. + */ +static void +parseWorkerCommand(ArchiveHandle *AH, TocEntry **te, T_Action *act, + const char *msg) +{ + DumpId dumpId; + int nBytes; + + if (messageStartsWith(msg, "DUMP ")) + { + *act = ACT_DUMP; + sscanf(msg, "DUMP %d%n", &dumpId, &nBytes); + Assert(nBytes == strlen(msg)); + *te = getTocEntryByDumpId(AH, dumpId); + Assert(*te != NULL); + } + else if (messageStartsWith(msg, "RESTORE ")) + { + *act = ACT_RESTORE; + sscanf(msg, "RESTORE %d%n", &dumpId, &nBytes); + Assert(nBytes == strlen(msg)); + *te = getTocEntryByDumpId(AH, dumpId); + Assert(*te != NULL); + } + else + fatal("unrecognized command received from leader: \"%s\"", + msg); +} + +/* + * buildWorkerResponse: format a response string to send to the leader. + * + * The string is built in the caller-supplied buffer of size buflen. + */ +static void +buildWorkerResponse(ArchiveHandle *AH, TocEntry *te, T_Action act, int status, + char *buf, int buflen) +{ + snprintf(buf, buflen, "OK %d %d %d", + te->dumpId, + status, + status == WORKER_IGNORED_ERRORS ? AH->public.n_errors : 0); +} + +/* + * parseWorkerResponse: parse the status message returned by a worker. + * + * Returns the integer status code, and may update fields of AH and/or te. + */ +static int +parseWorkerResponse(ArchiveHandle *AH, TocEntry *te, + const char *msg) +{ + DumpId dumpId; + int nBytes, + n_errors; + int status = 0; + + if (messageStartsWith(msg, "OK ")) + { + sscanf(msg, "OK %d %d %d%n", &dumpId, &status, &n_errors, &nBytes); + + Assert(dumpId == te->dumpId); + Assert(nBytes == strlen(msg)); + + AH->public.n_errors += n_errors; + } + else + fatal("invalid message received from worker: \"%s\"", + msg); + + return status; +} + +/* + * Dispatch a job to some free worker. + * + * te is the TocEntry to be processed, act is the action to be taken on it. + * callback is the function to call on completion of the job. + * + * If no worker is currently available, this will block, and previously + * registered callback functions may be called. + */ +void +DispatchJobForTocEntry(ArchiveHandle *AH, + ParallelState *pstate, + TocEntry *te, + T_Action act, + ParallelCompletionPtr callback, + void *callback_data) +{ + int worker; + char buf[256]; + + /* Get a worker, waiting if none are idle */ + while ((worker = GetIdleWorker(pstate)) == NO_SLOT) + WaitForWorkers(AH, pstate, WFW_ONE_IDLE); + + /* Construct and send command string */ + buildWorkerCommand(AH, te, act, buf, sizeof(buf)); + + sendMessageToWorker(pstate, worker, buf); + + /* Remember worker is busy, and which TocEntry it's working on */ + pstate->parallelSlot[worker].workerStatus = WRKR_WORKING; + pstate->parallelSlot[worker].callback = callback; + pstate->parallelSlot[worker].callback_data = callback_data; + pstate->te[worker] = te; +} + +/* + * Find an idle worker and return its slot number. + * Return NO_SLOT if none are idle. + */ +static int +GetIdleWorker(ParallelState *pstate) +{ + int i; + + for (i = 0; i < pstate->numWorkers; i++) + { + if (pstate->parallelSlot[i].workerStatus == WRKR_IDLE) + return i; + } + return NO_SLOT; +} + +/* + * Return true iff no worker is running. + */ +static bool +HasEveryWorkerTerminated(ParallelState *pstate) +{ + int i; + + for (i = 0; i < pstate->numWorkers; i++) + { + if (WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus)) + return false; + } + return true; +} + +/* + * Return true iff every worker is in the WRKR_IDLE state. + */ +bool +IsEveryWorkerIdle(ParallelState *pstate) +{ + int i; + + for (i = 0; i < pstate->numWorkers; i++) + { + if (pstate->parallelSlot[i].workerStatus != WRKR_IDLE) + return false; + } + return true; +} + +/* + * Acquire lock on a table to be dumped by a worker process. + * + * The leader process is already holding an ACCESS SHARE lock. Ordinarily + * it's no problem for a worker to get one too, but if anything else besides + * pg_dump is running, there's a possible deadlock: + * + * 1) Leader dumps the schema and locks all tables in ACCESS SHARE mode. + * 2) Another process requests an ACCESS EXCLUSIVE lock (which is not granted + * because the leader holds a conflicting ACCESS SHARE lock). + * 3) A worker process also requests an ACCESS SHARE lock to read the table. + * The worker is enqueued behind the ACCESS EXCLUSIVE lock request. + * 4) Now we have a deadlock, since the leader is effectively waiting for + * the worker. The server cannot detect that, however. + * + * To prevent an infinite wait, prior to touching a table in a worker, request + * a lock in ACCESS SHARE mode but with NOWAIT. If we don't get the lock, + * then we know that somebody else has requested an ACCESS EXCLUSIVE lock and + * so we have a deadlock. We must fail the backup in that case. + */ +static void +lockTableForWorker(ArchiveHandle *AH, TocEntry *te) +{ + const char *qualId; + PQExpBuffer query; + PGresult *res; + + /* Nothing to do for BLOBS */ + if (strcmp(te->desc, "BLOBS") == 0) + return; + + query = createPQExpBuffer(); + + qualId = fmtQualifiedId(te->namespace, te->tag); + + appendPQExpBuffer(query, "LOCK TABLE %s IN ACCESS SHARE MODE NOWAIT", + qualId); + + res = PQexec(AH->connection, query->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + fatal("could not obtain lock on relation \"%s\"\n" + "This usually means that someone requested an ACCESS EXCLUSIVE lock " + "on the table after the pg_dump parent process had gotten the " + "initial ACCESS SHARE lock on the table.", qualId); + + PQclear(res); + destroyPQExpBuffer(query); +} + +/* + * WaitForCommands: main routine for a worker process. + * + * Read and execute commands from the leader until we see EOF on the pipe. + */ +static void +WaitForCommands(ArchiveHandle *AH, int pipefd[2]) +{ + char *command; + TocEntry *te; + T_Action act; + int status = 0; + char buf[256]; + + for (;;) + { + if (!(command = getMessageFromLeader(pipefd))) + { + /* EOF, so done */ + return; + } + + /* Decode the command */ + parseWorkerCommand(AH, &te, &act, command); + + if (act == ACT_DUMP) + { + /* Acquire lock on this table within the worker's session */ + lockTableForWorker(AH, te); + + /* Perform the dump command */ + status = (AH->WorkerJobDumpPtr) (AH, te); + } + else if (act == ACT_RESTORE) + { + /* Perform the restore command */ + status = (AH->WorkerJobRestorePtr) (AH, te); + } + else + Assert(false); + + /* Return status to leader */ + buildWorkerResponse(AH, te, act, status, buf, sizeof(buf)); + + sendMessageToLeader(pipefd, buf); + + /* command was pg_malloc'd and we are responsible for free()ing it. */ + free(command); + } +} + +/* + * Check for status messages from workers. + * + * If do_wait is true, wait to get a status message; otherwise, just return + * immediately if there is none available. + * + * When we get a status message, we pass the status code to the callback + * function that was specified to DispatchJobForTocEntry, then reset the + * worker status to IDLE. + * + * Returns true if we collected a status message, else false. + * + * XXX is it worth checking for more than one status message per call? + * It seems somewhat unlikely that multiple workers would finish at exactly + * the same time. + */ +static bool +ListenToWorkers(ArchiveHandle *AH, ParallelState *pstate, bool do_wait) +{ + int worker; + char *msg; + + /* Try to collect a status message */ + msg = getMessageFromWorker(pstate, do_wait, &worker); + + if (!msg) + { + /* If do_wait is true, we must have detected EOF on some socket */ + if (do_wait) + fatal("a worker process died unexpectedly"); + return false; + } + + /* Process it and update our idea of the worker's status */ + if (messageStartsWith(msg, "OK ")) + { + ParallelSlot *slot = &pstate->parallelSlot[worker]; + TocEntry *te = pstate->te[worker]; + int status; + + status = parseWorkerResponse(AH, te, msg); + slot->callback(AH, te, status, slot->callback_data); + slot->workerStatus = WRKR_IDLE; + pstate->te[worker] = NULL; + } + else + fatal("invalid message received from worker: \"%s\"", + msg); + + /* Free the string returned from getMessageFromWorker */ + free(msg); + + return true; +} + +/* + * Check for status results from workers, waiting if necessary. + * + * Available wait modes are: + * WFW_NO_WAIT: reap any available status, but don't block + * WFW_GOT_STATUS: wait for at least one more worker to finish + * WFW_ONE_IDLE: wait for at least one worker to be idle + * WFW_ALL_IDLE: wait for all workers to be idle + * + * Any received results are passed to the callback specified to + * DispatchJobForTocEntry. + * + * This function is executed in the leader process. + */ +void +WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode) +{ + bool do_wait = false; + + /* + * In GOT_STATUS mode, always block waiting for a message, since we can't + * return till we get something. In other modes, we don't block the first + * time through the loop. + */ + if (mode == WFW_GOT_STATUS) + { + /* Assert that caller knows what it's doing */ + Assert(!IsEveryWorkerIdle(pstate)); + do_wait = true; + } + + for (;;) + { + /* + * Check for status messages, even if we don't need to block. We do + * not try very hard to reap all available messages, though, since + * there's unlikely to be more than one. + */ + if (ListenToWorkers(AH, pstate, do_wait)) + { + /* + * If we got a message, we are done by definition for GOT_STATUS + * mode, and we can also be certain that there's at least one idle + * worker. So we're done in all but ALL_IDLE mode. + */ + if (mode != WFW_ALL_IDLE) + return; + } + + /* Check whether we must wait for new status messages */ + switch (mode) + { + case WFW_NO_WAIT: + return; /* never wait */ + case WFW_GOT_STATUS: + Assert(false); /* can't get here, because we waited */ + break; + case WFW_ONE_IDLE: + if (GetIdleWorker(pstate) != NO_SLOT) + return; + break; + case WFW_ALL_IDLE: + if (IsEveryWorkerIdle(pstate)) + return; + break; + } + + /* Loop back, and this time wait for something to happen */ + do_wait = true; + } +} + +/* + * Read one command message from the leader, blocking if necessary + * until one is available, and return it as a malloc'd string. + * On EOF, return NULL. + * + * This function is executed in worker processes. + */ +static char * +getMessageFromLeader(int pipefd[2]) +{ + return readMessageFromPipe(pipefd[PIPE_READ]); +} + +/* + * Send a status message to the leader. + * + * This function is executed in worker processes. + */ +static void +sendMessageToLeader(int pipefd[2], const char *str) +{ + int len = strlen(str) + 1; + + if (pipewrite(pipefd[PIPE_WRITE], str, len) != len) + fatal("could not write to the communication channel: %m"); +} + +/* + * Wait until some descriptor in "workerset" becomes readable. + * Returns -1 on error, else the number of readable descriptors. + */ +static int +select_loop(int maxFd, fd_set *workerset) +{ + int i; + fd_set saveSet = *workerset; + + for (;;) + { + *workerset = saveSet; + i = select(maxFd + 1, workerset, NULL, NULL, NULL); + +#ifndef WIN32 + if (i < 0 && errno == EINTR) + continue; +#else + if (i == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) + continue; +#endif + break; + } + + return i; +} + + +/* + * Check for messages from worker processes. + * + * If a message is available, return it as a malloc'd string, and put the + * index of the sending worker in *worker. + * + * If nothing is available, wait if "do_wait" is true, else return NULL. + * + * If we detect EOF on any socket, we'll return NULL. It's not great that + * that's hard to distinguish from the no-data-available case, but for now + * our one caller is okay with that. + * + * This function is executed in the leader process. + */ +static char * +getMessageFromWorker(ParallelState *pstate, bool do_wait, int *worker) +{ + int i; + fd_set workerset; + int maxFd = -1; + struct timeval nowait = {0, 0}; + + /* construct bitmap of socket descriptors for select() */ + FD_ZERO(&workerset); + for (i = 0; i < pstate->numWorkers; i++) + { + if (!WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus)) + continue; + FD_SET(pstate->parallelSlot[i].pipeRead, &workerset); + if (pstate->parallelSlot[i].pipeRead > maxFd) + maxFd = pstate->parallelSlot[i].pipeRead; + } + + if (do_wait) + { + i = select_loop(maxFd, &workerset); + Assert(i != 0); + } + else + { + if ((i = select(maxFd + 1, &workerset, NULL, NULL, &nowait)) == 0) + return NULL; + } + + if (i < 0) + fatal("%s() failed: %m", "select"); + + for (i = 0; i < pstate->numWorkers; i++) + { + char *msg; + + if (!WORKER_IS_RUNNING(pstate->parallelSlot[i].workerStatus)) + continue; + if (!FD_ISSET(pstate->parallelSlot[i].pipeRead, &workerset)) + continue; + + /* + * Read the message if any. If the socket is ready because of EOF, + * we'll return NULL instead (and the socket will stay ready, so the + * condition will persist). + * + * Note: because this is a blocking read, we'll wait if only part of + * the message is available. Waiting a long time would be bad, but + * since worker status messages are short and are always sent in one + * operation, it shouldn't be a problem in practice. + */ + msg = readMessageFromPipe(pstate->parallelSlot[i].pipeRead); + *worker = i; + return msg; + } + Assert(false); + return NULL; +} + +/* + * Send a command message to the specified worker process. + * + * This function is executed in the leader process. + */ +static void +sendMessageToWorker(ParallelState *pstate, int worker, const char *str) +{ + int len = strlen(str) + 1; + + if (pipewrite(pstate->parallelSlot[worker].pipeWrite, str, len) != len) + { + fatal("could not write to the communication channel: %m"); + } +} + +/* + * Read one message from the specified pipe (fd), blocking if necessary + * until one is available, and return it as a malloc'd string. + * On EOF, return NULL. + * + * A "message" on the channel is just a null-terminated string. + */ +static char * +readMessageFromPipe(int fd) +{ + char *msg; + int msgsize, + bufsize; + int ret; + + /* + * In theory, if we let piperead() read multiple bytes, it might give us + * back fragments of multiple messages. (That can't actually occur, since + * neither leader nor workers send more than one message without waiting + * for a reply, but we don't wish to assume that here.) For simplicity, + * read a byte at a time until we get the terminating '\0'. This method + * is a bit inefficient, but since this is only used for relatively short + * command and status strings, it shouldn't matter. + */ + bufsize = 64; /* could be any number */ + msg = (char *) pg_malloc(bufsize); + msgsize = 0; + for (;;) + { + Assert(msgsize < bufsize); + ret = piperead(fd, msg + msgsize, 1); + if (ret <= 0) + break; /* error or connection closure */ + + Assert(ret == 1); + + if (msg[msgsize] == '\0') + return msg; /* collected whole message */ + + msgsize++; + if (msgsize == bufsize) /* enlarge buffer if needed */ + { + bufsize += 16; /* could be any number */ + msg = (char *) pg_realloc(msg, bufsize); + } + } + + /* Other end has closed the connection */ + pg_free(msg); + return NULL; +} + +#ifdef WIN32 + +/* + * This is a replacement version of pipe(2) for Windows which allows the pipe + * handles to be used in select(). + * + * Reads and writes on the pipe must go through piperead()/pipewrite(). + * + * For consistency with Unix we declare the returned handles as "int". + * This is okay even on WIN64 because system handles are not more than + * 32 bits wide, but we do have to do some casting. + */ +static int +pgpipe(int handles[2]) +{ + pgsocket s, + tmp_sock; + struct sockaddr_in serv_addr; + int len = sizeof(serv_addr); + + /* We have to use the Unix socket invalid file descriptor value here. */ + handles[0] = handles[1] = -1; + + /* + * setup listen socket + */ + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == PGINVALID_SOCKET) + { + pg_log_error("pgpipe: could not create socket: error code %d", + WSAGetLastError()); + return -1; + } + + memset((void *) &serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = pg_hton16(0); + serv_addr.sin_addr.s_addr = pg_hton32(INADDR_LOOPBACK); + if (bind(s, (SOCKADDR *) &serv_addr, len) == SOCKET_ERROR) + { + pg_log_error("pgpipe: could not bind: error code %d", + WSAGetLastError()); + closesocket(s); + return -1; + } + if (listen(s, 1) == SOCKET_ERROR) + { + pg_log_error("pgpipe: could not listen: error code %d", + WSAGetLastError()); + closesocket(s); + return -1; + } + if (getsockname(s, (SOCKADDR *) &serv_addr, &len) == SOCKET_ERROR) + { + pg_log_error("pgpipe: %s() failed: error code %d", "getsockname", + WSAGetLastError()); + closesocket(s); + return -1; + } + + /* + * setup pipe handles + */ + if ((tmp_sock = socket(AF_INET, SOCK_STREAM, 0)) == PGINVALID_SOCKET) + { + pg_log_error("pgpipe: could not create second socket: error code %d", + WSAGetLastError()); + closesocket(s); + return -1; + } + handles[1] = (int) tmp_sock; + + if (connect(handles[1], (SOCKADDR *) &serv_addr, len) == SOCKET_ERROR) + { + pg_log_error("pgpipe: could not connect socket: error code %d", + WSAGetLastError()); + closesocket(handles[1]); + handles[1] = -1; + closesocket(s); + return -1; + } + if ((tmp_sock = accept(s, (SOCKADDR *) &serv_addr, &len)) == PGINVALID_SOCKET) + { + pg_log_error("pgpipe: could not accept connection: error code %d", + WSAGetLastError()); + closesocket(handles[1]); + handles[1] = -1; + closesocket(s); + return -1; + } + handles[0] = (int) tmp_sock; + + closesocket(s); + return 0; +} + +#endif /* WIN32 */ diff --git a/src/bin/pg_dump/parallel.h b/src/bin/pg_dump/parallel.h new file mode 100644 index 0000000..0fbf736 --- /dev/null +++ b/src/bin/pg_dump/parallel.h @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------- + * + * parallel.h + * + * Parallel support for pg_dump and pg_restore + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/pg_dump/parallel.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DUMP_PARALLEL_H +#define PG_DUMP_PARALLEL_H + +#include "pg_backup_archiver.h" + +/* Function to call in leader process on completion of a worker task */ +typedef void (*ParallelCompletionPtr) (ArchiveHandle *AH, + TocEntry *te, + int status, + void *callback_data); + +/* Wait options for WaitForWorkers */ +typedef enum +{ + WFW_NO_WAIT, + WFW_GOT_STATUS, + WFW_ONE_IDLE, + WFW_ALL_IDLE +} WFW_WaitOption; + +/* ParallelSlot is an opaque struct known only within parallel.c */ +typedef struct ParallelSlot ParallelSlot; + +/* Overall state for parallel.c */ +typedef struct ParallelState +{ + int numWorkers; /* allowed number of workers */ + /* these arrays have numWorkers entries, one per worker: */ + TocEntry **te; /* item being worked on, or NULL */ + ParallelSlot *parallelSlot; /* private info about each worker */ +} ParallelState; + +#ifdef WIN32 +extern bool parallel_init_done; +extern DWORD mainThreadId; +#endif + +extern void init_parallel_dump_utils(void); + +extern bool IsEveryWorkerIdle(ParallelState *pstate); +extern void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, + WFW_WaitOption mode); + +extern ParallelState *ParallelBackupStart(ArchiveHandle *AH); +extern void DispatchJobForTocEntry(ArchiveHandle *AH, + ParallelState *pstate, + TocEntry *te, + T_Action act, + ParallelCompletionPtr callback, + void *callback_data); +extern void ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate); + +extern void set_archive_cancel_info(ArchiveHandle *AH, PGconn *conn); + +#endif /* PG_DUMP_PARALLEL_H */ diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h new file mode 100644 index 0000000..3c1cd85 --- /dev/null +++ b/src/bin/pg_dump/pg_backup.h @@ -0,0 +1,306 @@ +/*------------------------------------------------------------------------- + * + * pg_backup.h + * + * Public interface to the pg_dump archiver routines. + * + * See the headers to pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_BACKUP_H +#define PG_BACKUP_H + +#include "fe_utils/simple_list.h" +#include "libpq-fe.h" + + +typedef enum trivalue +{ + TRI_DEFAULT, + TRI_NO, + TRI_YES +} trivalue; + +typedef enum _archiveFormat +{ + archUnknown = 0, + archCustom = 1, + archTar = 3, + archNull = 4, + archDirectory = 5 +} ArchiveFormat; + +typedef enum _archiveMode +{ + archModeAppend, + archModeWrite, + archModeRead +} ArchiveMode; + +typedef enum _teSection +{ + SECTION_NONE = 1, /* COMMENTs, ACLs, etc; can be anywhere */ + SECTION_PRE_DATA, /* stuff to be processed before data */ + SECTION_DATA, /* TABLE DATA, BLOBS, BLOB COMMENTS */ + SECTION_POST_DATA /* stuff to be processed after data */ +} teSection; + +/* Parameters needed by ConnectDatabase; same for dump and restore */ +typedef struct _connParams +{ + /* These fields record the actual command line parameters */ + char *dbname; /* this may be a connstring! */ + char *pgport; + char *pghost; + char *username; + trivalue promptPassword; + /* If not NULL, this overrides the dbname obtained from command line */ + /* (but *only* the DB name, not anything else in the connstring) */ + char *override_dbname; +} ConnParams; + +typedef struct _restoreOptions +{ + int createDB; /* Issue commands to create the database */ + int noOwner; /* Don't try to match original object owner */ + int noTablespace; /* Don't issue tablespace-related commands */ + int disable_triggers; /* disable triggers during data-only + * restore */ + int use_setsessauth; /* Use SET SESSION AUTHORIZATION commands + * instead of OWNER TO */ + char *superuser; /* Username to use as superuser */ + char *use_role; /* Issue SET ROLE to this */ + int dropSchema; + int disable_dollar_quoting; + int dump_inserts; /* 0 = COPY, otherwise rows per INSERT */ + int column_inserts; + int if_exists; + int no_comments; /* Skip comments */ + int no_publications; /* Skip publication entries */ + int no_security_labels; /* Skip security label entries */ + int no_subscriptions; /* Skip subscription entries */ + int strict_names; + + const char *filename; + int dataOnly; + int schemaOnly; + int dumpSections; + int verbose; + int aclsSkip; + const char *lockWaitTimeout; + int include_everything; + + int tocSummary; + char *tocFile; + int format; + char *formatName; + + int selTypes; + int selIndex; + int selFunction; + int selTrigger; + int selTable; + SimpleStringList indexNames; + SimpleStringList functionNames; + SimpleStringList schemaNames; + SimpleStringList schemaExcludeNames; + SimpleStringList triggerNames; + SimpleStringList tableNames; + + int useDB; + ConnParams cparams; /* parameters to use if useDB */ + + int noDataForFailedTables; + int exit_on_error; + int compression; + int suppressDumpWarnings; /* Suppress output of WARNING entries + * to stderr */ + bool single_txn; + + bool *idWanted; /* array showing which dump IDs to emit */ + int enable_row_security; + int sequence_data; /* dump sequence data even in schema-only mode */ + int binary_upgrade; +} RestoreOptions; + +typedef struct _dumpOptions +{ + ConnParams cparams; + + int binary_upgrade; + + /* various user-settable parameters */ + bool schemaOnly; + bool dataOnly; + int dumpSections; /* bitmask of chosen sections */ + bool aclsSkip; + const char *lockWaitTimeout; + int dump_inserts; /* 0 = COPY, otherwise rows per INSERT */ + + /* flags for various command-line long options */ + int disable_dollar_quoting; + int column_inserts; + int if_exists; + int no_comments; + int no_security_labels; + int no_publications; + int no_subscriptions; + int no_synchronized_snapshots; + int no_toast_compression; + int no_unlogged_table_data; + int serializable_deferrable; + int disable_triggers; + int outputNoTablespaces; + int use_setsessauth; + int enable_row_security; + int load_via_partition_root; + + /* default, if no "inclusion" switches appear, is to dump everything */ + bool include_everything; + + int outputClean; + int outputCreateDB; + bool outputBlobs; + bool dontOutputBlobs; + int outputNoOwner; + char *outputSuperuser; + + int sequence_data; /* dump sequence data even in schema-only mode */ + int do_nothing; +} DumpOptions; + +/* + * We may want to have some more user-readable data, but in the mean + * time this gives us some abstraction and type checking. + */ +typedef struct Archive +{ + DumpOptions *dopt; /* options, if dumping */ + RestoreOptions *ropt; /* options, if restoring */ + + int verbose; + char *remoteVersionStr; /* server's version string */ + int remoteVersion; /* same in numeric form */ + bool isStandby; /* is server a standby node */ + + int minRemoteVersion; /* allowable range */ + int maxRemoteVersion; + + int numWorkers; /* number of parallel processes */ + char *sync_snapshot_id; /* sync snapshot id for parallel operation */ + + /* info needed for string escaping */ + int encoding; /* libpq code for client_encoding */ + bool std_strings; /* standard_conforming_strings */ + + /* other important stuff */ + char *searchpath; /* search_path to set during restore */ + char *use_role; /* Issue SET ROLE to this */ + + /* error handling */ + bool exit_on_error; /* whether to exit on SQL errors... */ + int n_errors; /* number of errors (if no die) */ + + /* The rest is private */ +} Archive; + + +/* + * pg_dump uses two different mechanisms for identifying database objects: + * + * CatalogId represents an object by the tableoid and oid of its defining + * entry in the system catalogs. We need this to interpret pg_depend entries, + * for instance. + * + * DumpId is a simple sequential integer counter assigned as dumpable objects + * are identified during a pg_dump run. We use DumpId internally in preference + * to CatalogId for two reasons: it's more compact, and we can assign DumpIds + * to "objects" that don't have a separate CatalogId. For example, it is + * convenient to consider a table, its data, and its ACL as three separate + * dumpable "objects" with distinct DumpIds --- this lets us reason about the + * order in which to dump these things. + */ + +typedef struct +{ + Oid tableoid; + Oid oid; +} CatalogId; + +typedef int DumpId; + +#define InvalidDumpId 0 + +/* + * Function pointer prototypes for assorted callback methods. + */ + +typedef int (*DataDumperPtr) (Archive *AH, const void *userArg); + +typedef void (*SetupWorkerPtrType) (Archive *AH); + +/* + * Main archiver interface. + */ + +extern void ConnectDatabase(Archive *AHX, + const ConnParams *cparams, + bool isReconnect); +extern void DisconnectDatabase(Archive *AHX); +extern PGconn *GetConnection(Archive *AHX); + +/* Called to write *data* to the archive */ +extern void WriteData(Archive *AH, const void *data, size_t dLen); + +extern int StartBlob(Archive *AH, Oid oid); +extern int EndBlob(Archive *AH, Oid oid); + +extern void CloseArchive(Archive *AH); + +extern void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt); + +extern void ProcessArchiveRestoreOptions(Archive *AH); + +extern void RestoreArchive(Archive *AH); + +/* Open an existing archive */ +extern Archive *OpenArchive(const char *FileSpec, const ArchiveFormat fmt); + +/* Create a new archive */ +extern Archive *CreateArchive(const char *FileSpec, const ArchiveFormat fmt, + const int compression, bool dosync, ArchiveMode mode, + SetupWorkerPtrType setupDumpWorker); + +/* The --list option */ +extern void PrintTOCSummary(Archive *AH); + +extern RestoreOptions *NewRestoreOptions(void); + +extern DumpOptions *NewDumpOptions(void); +extern void InitDumpOptions(DumpOptions *opts); +extern DumpOptions *dumpOptionsFromRestoreOptions(RestoreOptions *ropt); + +/* Rearrange and filter TOC entries */ +extern void SortTocFromFile(Archive *AHX); + +/* Convenience functions used only when writing DATA */ +extern void archputs(const char *s, Archive *AH); +extern int archprintf(Archive *AH, const char *fmt,...) pg_attribute_printf(2, 3); + +#define appendStringLiteralAH(buf,str,AH) \ + appendStringLiteral(buf, str, (AH)->encoding, (AH)->std_strings) + +#endif /* PG_BACKUP_H */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c new file mode 100644 index 0000000..87113cf --- /dev/null +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -0,0 +1,4824 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_archiver.c + * + * Private implementation of the archiver routines. + * + * See the headers to pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_archiver.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#endif + +#include "common/string.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" +#include "lib/stringinfo.h" +#include "libpq/libpq-fs.h" +#include "parallel.h" +#include "pg_backup_archiver.h" +#include "pg_backup_db.h" +#include "pg_backup_utils.h" + +#define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n" +#define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n" + +/* state needed to save/restore an archive's output target */ +typedef struct _outputContext +{ + void *OF; + int gzOut; +} OutputContext; + +/* + * State for tracking TocEntrys that are ready to process during a parallel + * restore. (This used to be a list, and we still call it that, though now + * it's really an array so that we can apply qsort to it.) + * + * tes[] is sized large enough that we can't overrun it. + * The valid entries are indexed first_te .. last_te inclusive. + * We periodically sort the array to bring larger-by-dataLength entries to + * the front; "sorted" is true if the valid entries are known sorted. + */ +typedef struct _parallelReadyList +{ + TocEntry **tes; /* Ready-to-dump TocEntrys */ + int first_te; /* index of first valid entry in tes[] */ + int last_te; /* index of last valid entry in tes[] */ + bool sorted; /* are valid entries currently sorted? */ +} ParallelReadyList; + + +static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, + const int compression, bool dosync, ArchiveMode mode, + SetupWorkerPtrType setupWorkerPtr); +static void _getObjectDescription(PQExpBuffer buf, TocEntry *te); +static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData); +static char *sanitize_line(const char *str, bool want_hyphen); +static void _doSetFixedOutputState(ArchiveHandle *AH); +static void _doSetSessionAuth(ArchiveHandle *AH, const char *user); +static void _reconnectToDB(ArchiveHandle *AH, const char *dbname); +static void _becomeUser(ArchiveHandle *AH, const char *user); +static void _becomeOwner(ArchiveHandle *AH, TocEntry *te); +static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); +static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); +static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam); +static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); +static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); +static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te); +static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH); +static RestorePass _tocEntryRestorePass(TocEntry *te); +static bool _tocEntryIsACL(TocEntry *te); +static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te); +static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te); +static void buildTocEntryArrays(ArchiveHandle *AH); +static void _moveBefore(TocEntry *pos, TocEntry *te); +static int _discoverArchiveFormat(ArchiveHandle *AH); + +static int RestoringToDB(ArchiveHandle *AH); +static void dump_lo_buf(ArchiveHandle *AH); +static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim); +static void SetOutput(ArchiveHandle *AH, const char *filename, int compression); +static OutputContext SaveOutput(ArchiveHandle *AH); +static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext); + +static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel); +static void restore_toc_entries_prefork(ArchiveHandle *AH, + TocEntry *pending_list); +static void restore_toc_entries_parallel(ArchiveHandle *AH, + ParallelState *pstate, + TocEntry *pending_list); +static void restore_toc_entries_postfork(ArchiveHandle *AH, + TocEntry *pending_list); +static void pending_list_header_init(TocEntry *l); +static void pending_list_append(TocEntry *l, TocEntry *te); +static void pending_list_remove(TocEntry *te); +static void ready_list_init(ParallelReadyList *ready_list, int tocCount); +static void ready_list_free(ParallelReadyList *ready_list); +static void ready_list_insert(ParallelReadyList *ready_list, TocEntry *te); +static void ready_list_remove(ParallelReadyList *ready_list, int i); +static void ready_list_sort(ParallelReadyList *ready_list); +static int TocEntrySizeCompare(const void *p1, const void *p2); +static void move_to_ready_list(TocEntry *pending_list, + ParallelReadyList *ready_list, + RestorePass pass); +static TocEntry *pop_next_work_item(ParallelReadyList *ready_list, + ParallelState *pstate); +static void mark_dump_job_done(ArchiveHandle *AH, + TocEntry *te, + int status, + void *callback_data); +static void mark_restore_job_done(ArchiveHandle *AH, + TocEntry *te, + int status, + void *callback_data); +static void fix_dependencies(ArchiveHandle *AH); +static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2); +static void repoint_table_dependencies(ArchiveHandle *AH); +static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te); +static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, + ParallelReadyList *ready_list); +static void mark_create_done(ArchiveHandle *AH, TocEntry *te); +static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te); + +static void StrictNamesCheck(RestoreOptions *ropt); + + +/* + * Allocate a new DumpOptions block containing all default values. + */ +DumpOptions * +NewDumpOptions(void) +{ + DumpOptions *opts = (DumpOptions *) pg_malloc(sizeof(DumpOptions)); + + InitDumpOptions(opts); + return opts; +} + +/* + * Initialize a DumpOptions struct to all default values + */ +void +InitDumpOptions(DumpOptions *opts) +{ + memset(opts, 0, sizeof(DumpOptions)); + /* set any fields that shouldn't default to zeroes */ + opts->include_everything = true; + opts->cparams.promptPassword = TRI_DEFAULT; + opts->dumpSections = DUMP_UNSECTIONED; +} + +/* + * Create a freshly allocated DumpOptions with options equivalent to those + * found in the given RestoreOptions. + */ +DumpOptions * +dumpOptionsFromRestoreOptions(RestoreOptions *ropt) +{ + DumpOptions *dopt = NewDumpOptions(); + + /* this is the inverse of what's at the end of pg_dump.c's main() */ + dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL; + dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL; + dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL; + dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL; + dopt->cparams.promptPassword = ropt->cparams.promptPassword; + dopt->outputClean = ropt->dropSchema; + dopt->dataOnly = ropt->dataOnly; + dopt->schemaOnly = ropt->schemaOnly; + dopt->if_exists = ropt->if_exists; + dopt->column_inserts = ropt->column_inserts; + dopt->dumpSections = ropt->dumpSections; + dopt->aclsSkip = ropt->aclsSkip; + dopt->outputSuperuser = ropt->superuser; + dopt->outputCreateDB = ropt->createDB; + dopt->outputNoOwner = ropt->noOwner; + dopt->outputNoTablespaces = ropt->noTablespace; + dopt->disable_triggers = ropt->disable_triggers; + dopt->use_setsessauth = ropt->use_setsessauth; + dopt->disable_dollar_quoting = ropt->disable_dollar_quoting; + dopt->dump_inserts = ropt->dump_inserts; + dopt->no_comments = ropt->no_comments; + dopt->no_publications = ropt->no_publications; + dopt->no_security_labels = ropt->no_security_labels; + dopt->no_subscriptions = ropt->no_subscriptions; + dopt->lockWaitTimeout = ropt->lockWaitTimeout; + dopt->include_everything = ropt->include_everything; + dopt->enable_row_security = ropt->enable_row_security; + dopt->sequence_data = ropt->sequence_data; + + return dopt; +} + + +/* + * Wrapper functions. + * + * The objective is to make writing new formats and dumpers as simple + * as possible, if necessary at the expense of extra function calls etc. + * + */ + +/* + * The dump worker setup needs lots of knowledge of the internals of pg_dump, + * so it's defined in pg_dump.c and passed into OpenArchive. The restore worker + * setup doesn't need to know anything much, so it's defined here. + */ +static void +setupRestoreWorker(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + AH->ReopenPtr(AH); +} + + +/* Create a new archive */ +/* Public */ +Archive * +CreateArchive(const char *FileSpec, const ArchiveFormat fmt, + const int compression, bool dosync, ArchiveMode mode, + SetupWorkerPtrType setupDumpWorker) + +{ + ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, dosync, + mode, setupDumpWorker); + + return (Archive *) AH; +} + +/* Open an existing archive */ +/* Public */ +Archive * +OpenArchive(const char *FileSpec, const ArchiveFormat fmt) +{ + ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, true, archModeRead, setupRestoreWorker); + + return (Archive *) AH; +} + +/* Public */ +void +CloseArchive(Archive *AHX) +{ + int res = 0; + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + AH->ClosePtr(AH); + + /* Close the output */ + errno = 0; /* in case gzclose() doesn't set it */ + if (AH->gzOut) + res = GZCLOSE(AH->OF); + else if (AH->OF != stdout) + res = fclose(AH->OF); + + if (res != 0) + fatal("could not close output file: %m"); +} + +/* Public */ +void +SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt) +{ + /* Caller can omit dump options, in which case we synthesize them */ + if (dopt == NULL && ropt != NULL) + dopt = dumpOptionsFromRestoreOptions(ropt); + + /* Save options for later access */ + AH->dopt = dopt; + AH->ropt = ropt; +} + +/* Public */ +void +ProcessArchiveRestoreOptions(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + RestoreOptions *ropt = AH->public.ropt; + TocEntry *te; + teSection curSection; + + /* Decide which TOC entries will be dumped/restored, and mark them */ + curSection = SECTION_PRE_DATA; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + /* + * When writing an archive, we also take this opportunity to check + * that we have generated the entries in a sane order that respects + * the section divisions. When reading, don't complain, since buggy + * old versions of pg_dump might generate out-of-order archives. + */ + if (AH->mode != archModeRead) + { + switch (te->section) + { + case SECTION_NONE: + /* ok to be anywhere */ + break; + case SECTION_PRE_DATA: + if (curSection != SECTION_PRE_DATA) + pg_log_warning("archive items not in correct section order"); + break; + case SECTION_DATA: + if (curSection == SECTION_POST_DATA) + pg_log_warning("archive items not in correct section order"); + break; + case SECTION_POST_DATA: + /* ok no matter which section we were in */ + break; + default: + fatal("unexpected section code %d", + (int) te->section); + break; + } + } + + if (te->section != SECTION_NONE) + curSection = te->section; + + te->reqs = _tocEntryRequired(te, curSection, AH); + } + + /* Enforce strict names checking */ + if (ropt->strict_names) + StrictNamesCheck(ropt); +} + +/* Public */ +void +RestoreArchive(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + RestoreOptions *ropt = AH->public.ropt; + bool parallel_mode; + TocEntry *te; + OutputContext sav; + + AH->stage = STAGE_INITIALIZING; + + /* + * If we're going to do parallel restore, there are some restrictions. + */ + parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB); + if (parallel_mode) + { + /* We haven't got round to making this work for all archive formats */ + if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL) + fatal("parallel restore is not supported with this archive file format"); + + /* Doesn't work if the archive represents dependencies as OIDs */ + if (AH->version < K_VERS_1_8) + fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump"); + + /* + * It's also not gonna work if we can't reopen the input file, so + * let's try that immediately. + */ + AH->ReopenPtr(AH); + } + + /* + * Make sure we won't need (de)compression we haven't got + */ +#ifndef HAVE_LIBZ + if (AH->compression != 0 && AH->PrintTocDataPtr != NULL) + { + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (te->hadDumper && (te->reqs & REQ_DATA) != 0) + fatal("cannot restore from compressed archive (compression not supported in this installation)"); + } + } +#endif + + /* + * Prepare index arrays, so we can assume we have them throughout restore. + * It's possible we already did this, though. + */ + if (AH->tocsByDumpId == NULL) + buildTocEntryArrays(AH); + + /* + * If we're using a DB connection, then connect it. + */ + if (ropt->useDB) + { + pg_log_info("connecting to database for restore"); + if (AH->version < K_VERS_1_3) + fatal("direct database connections are not supported in pre-1.3 archives"); + + /* + * We don't want to guess at whether the dump will successfully + * restore; allow the attempt regardless of the version of the restore + * target. + */ + AHX->minRemoteVersion = 0; + AHX->maxRemoteVersion = 9999999; + + ConnectDatabase(AHX, &ropt->cparams, false); + + /* + * If we're talking to the DB directly, don't send comments since they + * obscure SQL when displaying errors + */ + AH->noTocComments = 1; + } + + /* + * Work out if we have an implied data-only restore. This can happen if + * the dump was data only or if the user has used a toc list to exclude + * all of the schema data. All we do is look for schema entries - if none + * are found then we set the dataOnly flag. + * + * We could scan for wanted TABLE entries, but that is not the same as + * dataOnly. At this stage, it seems unnecessary (6-Mar-2001). + */ + if (!ropt->dataOnly) + { + int impliedDataOnly = 1; + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & REQ_SCHEMA) != 0) + { /* It's schema, and it's wanted */ + impliedDataOnly = 0; + break; + } + } + if (impliedDataOnly) + { + ropt->dataOnly = impliedDataOnly; + pg_log_info("implied data-only restore"); + } + } + + /* + * Setup the output file if necessary. + */ + sav = SaveOutput(AH); + if (ropt->filename || ropt->compression) + SetOutput(AH, ropt->filename, ropt->compression); + + ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n"); + + if (AH->archiveRemoteVersion) + ahprintf(AH, "-- Dumped from database version %s\n", + AH->archiveRemoteVersion); + if (AH->archiveDumpVersion) + ahprintf(AH, "-- Dumped by pg_dump version %s\n", + AH->archiveDumpVersion); + + ahprintf(AH, "\n"); + + if (AH->public.verbose) + dumpTimestamp(AH, "Started on", AH->createDate); + + if (ropt->single_txn) + { + if (AH->connection) + StartTransaction(AHX); + else + ahprintf(AH, "BEGIN;\n\n"); + } + + /* + * Establish important parameter values right away. + */ + _doSetFixedOutputState(AH); + + AH->stage = STAGE_PROCESSING; + + /* + * Drop the items at the start, in reverse order + */ + if (ropt->dropSchema) + { + for (te = AH->toc->prev; te != AH->toc; te = te->prev) + { + AH->currentTE = te; + + /* + * In createDB mode, issue a DROP *only* for the database as a + * whole. Issuing drops against anything else would be wrong, + * because at this point we're connected to the wrong database. + * (The DATABASE PROPERTIES entry, if any, should be treated like + * the DATABASE entry.) + */ + if (ropt->createDB) + { + if (strcmp(te->desc, "DATABASE") != 0 && + strcmp(te->desc, "DATABASE PROPERTIES") != 0) + continue; + } + + /* Otherwise, drop anything that's selected and has a dropStmt */ + if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt) + { + pg_log_info("dropping %s %s", te->desc, te->tag); + /* Select owner and schema as necessary */ + _becomeOwner(AH, te); + _selectOutputSchema(AH, te->namespace); + + /* + * Now emit the DROP command, if the object has one. Note we + * don't necessarily emit it verbatim; at this point we add an + * appropriate IF EXISTS clause, if the user requested it. + */ + if (*te->dropStmt != '\0') + { + if (!ropt->if_exists) + { + /* No --if-exists? Then just use the original */ + ahprintf(AH, "%s", te->dropStmt); + } + else + { + /* + * Inject an appropriate spelling of "if exists". For + * large objects, we have a separate routine that + * knows how to do it, without depending on + * te->dropStmt; use that. For other objects we need + * to parse the command. + */ + if (strncmp(te->desc, "BLOB", 4) == 0) + { + DropBlobIfExists(AH, te->catalogId.oid); + } + else + { + char *dropStmt = pg_strdup(te->dropStmt); + char *dropStmtOrig = dropStmt; + PQExpBuffer ftStmt = createPQExpBuffer(); + + /* + * Need to inject IF EXISTS clause after ALTER + * TABLE part in ALTER TABLE .. DROP statement + */ + if (strncmp(dropStmt, "ALTER TABLE", 11) == 0) + { + appendPQExpBufferStr(ftStmt, + "ALTER TABLE IF EXISTS"); + dropStmt = dropStmt + 11; + } + + /* + * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does + * not support the IF EXISTS clause, and therefore + * we simply emit the original command for DEFAULT + * objects (modulo the adjustment made above). + * + * Likewise, don't mess with DATABASE PROPERTIES. + * + * If we used CREATE OR REPLACE VIEW as a means of + * quasi-dropping an ON SELECT rule, that should + * be emitted unchanged as well. + * + * For other object types, we need to extract the + * first part of the DROP which includes the + * object type. Most of the time this matches + * te->desc, so search for that; however for the + * different kinds of CONSTRAINTs, we know to + * search for hardcoded "DROP CONSTRAINT" instead. + */ + if (strcmp(te->desc, "DEFAULT") == 0 || + strcmp(te->desc, "DATABASE PROPERTIES") == 0 || + strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0) + appendPQExpBufferStr(ftStmt, dropStmt); + else + { + char buffer[40]; + char *mark; + + if (strcmp(te->desc, "CONSTRAINT") == 0 || + strcmp(te->desc, "CHECK CONSTRAINT") == 0 || + strcmp(te->desc, "FK CONSTRAINT") == 0) + strcpy(buffer, "DROP CONSTRAINT"); + else + snprintf(buffer, sizeof(buffer), "DROP %s", + te->desc); + + mark = strstr(dropStmt, buffer); + + if (mark) + { + *mark = '\0'; + appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s", + dropStmt, buffer, + mark + strlen(buffer)); + } + else + { + /* complain and emit unmodified command */ + pg_log_warning("could not find where to insert IF EXISTS in statement \"%s\"", + dropStmtOrig); + appendPQExpBufferStr(ftStmt, dropStmt); + } + } + + ahprintf(AH, "%s", ftStmt->data); + + destroyPQExpBuffer(ftStmt); + pg_free(dropStmtOrig); + } + } + } + } + } + + /* + * _selectOutputSchema may have set currSchema to reflect the effect + * of a "SET search_path" command it emitted. However, by now we may + * have dropped that schema; or it might not have existed in the first + * place. In either case the effective value of search_path will not + * be what we think. Forcibly reset currSchema so that we will + * re-establish the search_path setting when needed (after creating + * the schema). + * + * If we treated users as pg_dump'able objects then we'd need to reset + * currUser here too. + */ + if (AH->currSchema) + free(AH->currSchema); + AH->currSchema = NULL; + } + + if (parallel_mode) + { + /* + * In parallel mode, turn control over to the parallel-restore logic. + */ + ParallelState *pstate; + TocEntry pending_list; + + /* The archive format module may need some setup for this */ + if (AH->PrepParallelRestorePtr) + AH->PrepParallelRestorePtr(AH); + + pending_list_header_init(&pending_list); + + /* This runs PRE_DATA items and then disconnects from the database */ + restore_toc_entries_prefork(AH, &pending_list); + Assert(AH->connection == NULL); + + /* ParallelBackupStart() will actually fork the processes */ + pstate = ParallelBackupStart(AH); + restore_toc_entries_parallel(AH, pstate, &pending_list); + ParallelBackupEnd(AH, pstate); + + /* reconnect the leader and see if we missed something */ + restore_toc_entries_postfork(AH, &pending_list); + Assert(AH->connection != NULL); + } + else + { + /* + * In serial mode, process everything in three phases: normal items, + * then ACLs, then post-ACL items. We might be able to skip one or + * both extra phases in some cases, eg data-only restores. + */ + bool haveACL = false; + bool havePostACL = false; + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) == 0) + continue; /* ignore if not to be dumped at all */ + + switch (_tocEntryRestorePass(te)) + { + case RESTORE_PASS_MAIN: + (void) restore_toc_entry(AH, te, false); + break; + case RESTORE_PASS_ACL: + haveACL = true; + break; + case RESTORE_PASS_POST_ACL: + havePostACL = true; + break; + } + } + + if (haveACL) + { + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && + _tocEntryRestorePass(te) == RESTORE_PASS_ACL) + (void) restore_toc_entry(AH, te, false); + } + } + + if (havePostACL) + { + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && + _tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL) + (void) restore_toc_entry(AH, te, false); + } + } + } + + if (ropt->single_txn) + { + if (AH->connection) + CommitTransaction(AHX); + else + ahprintf(AH, "COMMIT;\n\n"); + } + + if (AH->public.verbose) + dumpTimestamp(AH, "Completed on", time(NULL)); + + ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n"); + + /* + * Clean up & we're done. + */ + AH->stage = STAGE_FINALIZING; + + if (ropt->filename || ropt->compression) + RestoreOutput(AH, sav); + + if (ropt->useDB) + DisconnectDatabase(&AH->public); +} + +/* + * Restore a single TOC item. Used in both parallel and non-parallel restore; + * is_parallel is true if we are in a worker child process. + * + * Returns 0 normally, but WORKER_CREATE_DONE or WORKER_INHIBIT_DATA if + * the parallel parent has to make the corresponding status update. + */ +static int +restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) +{ + RestoreOptions *ropt = AH->public.ropt; + int status = WORKER_OK; + int reqs; + bool defnDumped; + + AH->currentTE = te; + + /* Dump any relevant dump warnings to stderr */ + if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0) + { + if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0) + pg_log_warning("warning from original dump file: %s", te->defn); + else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0) + pg_log_warning("warning from original dump file: %s", te->copyStmt); + } + + /* Work out what, if anything, we want from this entry */ + reqs = te->reqs; + + defnDumped = false; + + /* + * If it has a schema component that we want, then process that + */ + if ((reqs & REQ_SCHEMA) != 0) + { + /* Show namespace in log message if available */ + if (te->namespace) + pg_log_info("creating %s \"%s.%s\"", + te->desc, te->namespace, te->tag); + else + pg_log_info("creating %s \"%s\"", + te->desc, te->tag); + + _printTocEntry(AH, te, false); + defnDumped = true; + + if (strcmp(te->desc, "TABLE") == 0) + { + if (AH->lastErrorTE == te) + { + /* + * We failed to create the table. If + * --no-data-for-failed-tables was given, mark the + * corresponding TABLE DATA to be ignored. + * + * In the parallel case this must be done in the parent, so we + * just set the return value. + */ + if (ropt->noDataForFailedTables) + { + if (is_parallel) + status = WORKER_INHIBIT_DATA; + else + inhibit_data_for_failed_table(AH, te); + } + } + else + { + /* + * We created the table successfully. Mark the corresponding + * TABLE DATA for possible truncation. + * + * In the parallel case this must be done in the parent, so we + * just set the return value. + */ + if (is_parallel) + status = WORKER_CREATE_DONE; + else + mark_create_done(AH, te); + } + } + + /* + * If we created a DB, connect to it. Also, if we changed DB + * properties, reconnect to ensure that relevant GUC settings are + * applied to our session. + */ + if (strcmp(te->desc, "DATABASE") == 0 || + strcmp(te->desc, "DATABASE PROPERTIES") == 0) + { + pg_log_info("connecting to new database \"%s\"", te->tag); + _reconnectToDB(AH, te->tag); + } + } + + /* + * If it has a data component that we want, then process that + */ + if ((reqs & REQ_DATA) != 0) + { + /* + * hadDumper will be set if there is genuine data component for this + * node. Otherwise, we need to check the defn field for statements + * that need to be executed in data-only restores. + */ + if (te->hadDumper) + { + /* + * If we can output the data, then restore it. + */ + if (AH->PrintTocDataPtr != NULL) + { + _printTocEntry(AH, te, true); + + if (strcmp(te->desc, "BLOBS") == 0 || + strcmp(te->desc, "BLOB COMMENTS") == 0) + { + pg_log_info("processing %s", te->desc); + + _selectOutputSchema(AH, "pg_catalog"); + + /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */ + if (strcmp(te->desc, "BLOB COMMENTS") == 0) + AH->outputKind = OUTPUT_OTHERDATA; + + AH->PrintTocDataPtr(AH, te); + + AH->outputKind = OUTPUT_SQLCMDS; + } + else + { + _disableTriggersIfNecessary(AH, te); + + /* Select owner and schema as necessary */ + _becomeOwner(AH, te); + _selectOutputSchema(AH, te->namespace); + + pg_log_info("processing data for table \"%s.%s\"", + te->namespace, te->tag); + + /* + * In parallel restore, if we created the table earlier in + * the run then we wrap the COPY in a transaction and + * precede it with a TRUNCATE. If archiving is not on + * this prevents WAL-logging the COPY. This obtains a + * speedup similar to that from using single_txn mode in + * non-parallel restores. + */ + if (is_parallel && te->created) + { + /* + * Parallel restore is always talking directly to a + * server, so no need to see if we should issue BEGIN. + */ + StartTransaction(&AH->public); + + /* + * If the server version is >= 8.4, make sure we issue + * TRUNCATE with ONLY so that child tables are not + * wiped. + */ + ahprintf(AH, "TRUNCATE TABLE %s%s;\n\n", + (PQserverVersion(AH->connection) >= 80400 ? + "ONLY " : ""), + fmtQualifiedId(te->namespace, te->tag)); + } + + /* + * If we have a copy statement, use it. + */ + if (te->copyStmt && strlen(te->copyStmt) > 0) + { + ahprintf(AH, "%s", te->copyStmt); + AH->outputKind = OUTPUT_COPYDATA; + } + else + AH->outputKind = OUTPUT_OTHERDATA; + + AH->PrintTocDataPtr(AH, te); + + /* + * Terminate COPY if needed. + */ + if (AH->outputKind == OUTPUT_COPYDATA && + RestoringToDB(AH)) + EndDBCopyMode(&AH->public, te->tag); + AH->outputKind = OUTPUT_SQLCMDS; + + /* close out the transaction started above */ + if (is_parallel && te->created) + CommitTransaction(&AH->public); + + _enableTriggersIfNecessary(AH, te); + } + } + } + else if (!defnDumped) + { + /* If we haven't already dumped the defn part, do so now */ + pg_log_info("executing %s %s", te->desc, te->tag); + _printTocEntry(AH, te, false); + } + } + + if (AH->public.n_errors > 0 && status == WORKER_OK) + status = WORKER_IGNORED_ERRORS; + + return status; +} + +/* + * Allocate a new RestoreOptions block. + * This is mainly so we can initialize it, but also for future expansion, + */ +RestoreOptions * +NewRestoreOptions(void) +{ + RestoreOptions *opts; + + opts = (RestoreOptions *) pg_malloc0(sizeof(RestoreOptions)); + + /* set any fields that shouldn't default to zeroes */ + opts->format = archUnknown; + opts->cparams.promptPassword = TRI_DEFAULT; + opts->dumpSections = DUMP_UNSECTIONED; + + return opts; +} + +static void +_disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te) +{ + RestoreOptions *ropt = AH->public.ropt; + + /* This hack is only needed in a data-only restore */ + if (!ropt->dataOnly || !ropt->disable_triggers) + return; + + pg_log_info("disabling triggers for %s", te->tag); + + /* + * Become superuser if possible, since they are the only ones who can + * disable constraint triggers. If -S was not given, assume the initial + * user identity is a superuser. (XXX would it be better to become the + * table owner?) + */ + _becomeUser(AH, ropt->superuser); + + /* + * Disable them. + */ + ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n", + fmtQualifiedId(te->namespace, te->tag)); +} + +static void +_enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te) +{ + RestoreOptions *ropt = AH->public.ropt; + + /* This hack is only needed in a data-only restore */ + if (!ropt->dataOnly || !ropt->disable_triggers) + return; + + pg_log_info("enabling triggers for %s", te->tag); + + /* + * Become superuser if possible, since they are the only ones who can + * disable constraint triggers. If -S was not given, assume the initial + * user identity is a superuser. (XXX would it be better to become the + * table owner?) + */ + _becomeUser(AH, ropt->superuser); + + /* + * Enable them. + */ + ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n", + fmtQualifiedId(te->namespace, te->tag)); +} + +/* + * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter. + */ + +/* Public */ +void +WriteData(Archive *AHX, const void *data, size_t dLen) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + if (!AH->currToc) + fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine"); + + AH->WriteDataPtr(AH, data, dLen); +} + +/* + * Create a new TOC entry. The TOC was designed as a TOC, but is now the + * repository for all metadata. But the name has stuck. + * + * The new entry is added to the Archive's TOC list. Most callers can ignore + * the result value because nothing else need be done, but a few want to + * manipulate the TOC entry further. + */ + +/* Public */ +TocEntry * +ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId, + ArchiveOpts *opts) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + TocEntry *newToc; + + newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry)); + + AH->tocCount++; + if (dumpId > AH->maxDumpId) + AH->maxDumpId = dumpId; + + newToc->prev = AH->toc->prev; + newToc->next = AH->toc; + AH->toc->prev->next = newToc; + AH->toc->prev = newToc; + + newToc->catalogId = catalogId; + newToc->dumpId = dumpId; + newToc->section = opts->section; + + newToc->tag = pg_strdup(opts->tag); + newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL; + newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL; + newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL; + newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL; + newToc->desc = pg_strdup(opts->description); + newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL; + newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL; + newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL; + + if (opts->nDeps > 0) + { + newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId)); + memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId)); + newToc->nDeps = opts->nDeps; + } + else + { + newToc->dependencies = NULL; + newToc->nDeps = 0; + } + + newToc->dataDumper = opts->dumpFn; + newToc->dataDumperArg = opts->dumpArg; + newToc->hadDumper = opts->dumpFn ? true : false; + + newToc->formatData = NULL; + newToc->dataLength = 0; + + if (AH->ArchiveEntryPtr != NULL) + AH->ArchiveEntryPtr(AH, newToc); + + return newToc; +} + +/* Public */ +void +PrintTOCSummary(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + RestoreOptions *ropt = AH->public.ropt; + TocEntry *te; + teSection curSection; + OutputContext sav; + const char *fmtName; + char stamp_str[64]; + + sav = SaveOutput(AH); + if (ropt->filename) + SetOutput(AH, ropt->filename, 0 /* no compression */ ); + + if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT, + localtime(&AH->createDate)) == 0) + strcpy(stamp_str, "[unknown]"); + + ahprintf(AH, ";\n; Archive created at %s\n", stamp_str); + ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n", + sanitize_line(AH->archdbname, false), + AH->tocCount, AH->compression); + + switch (AH->format) + { + case archCustom: + fmtName = "CUSTOM"; + break; + case archDirectory: + fmtName = "DIRECTORY"; + break; + case archTar: + fmtName = "TAR"; + break; + default: + fmtName = "UNKNOWN"; + } + + ahprintf(AH, "; Dump Version: %d.%d-%d\n", + ARCHIVE_MAJOR(AH->version), ARCHIVE_MINOR(AH->version), ARCHIVE_REV(AH->version)); + ahprintf(AH, "; Format: %s\n", fmtName); + ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize); + ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize); + if (AH->archiveRemoteVersion) + ahprintf(AH, "; Dumped from database version: %s\n", + AH->archiveRemoteVersion); + if (AH->archiveDumpVersion) + ahprintf(AH, "; Dumped by pg_dump version: %s\n", + AH->archiveDumpVersion); + + ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n"); + + curSection = SECTION_PRE_DATA; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (te->section != SECTION_NONE) + curSection = te->section; + if (ropt->verbose || + (_tocEntryRequired(te, curSection, AH) & (REQ_SCHEMA | REQ_DATA)) != 0) + { + char *sanitized_name; + char *sanitized_schema; + char *sanitized_owner; + + /* + */ + sanitized_name = sanitize_line(te->tag, false); + sanitized_schema = sanitize_line(te->namespace, true); + sanitized_owner = sanitize_line(te->owner, false); + + ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId, + te->catalogId.tableoid, te->catalogId.oid, + te->desc, sanitized_schema, sanitized_name, + sanitized_owner); + + free(sanitized_name); + free(sanitized_schema); + free(sanitized_owner); + } + if (ropt->verbose && te->nDeps > 0) + { + int i; + + ahprintf(AH, ";\tdepends on:"); + for (i = 0; i < te->nDeps; i++) + ahprintf(AH, " %d", te->dependencies[i]); + ahprintf(AH, "\n"); + } + } + + /* Enforce strict names checking */ + if (ropt->strict_names) + StrictNamesCheck(ropt); + + if (ropt->filename) + RestoreOutput(AH, sav); +} + +/*********** + * BLOB Archival + ***********/ + +/* Called by a dumper to signal start of a BLOB */ +int +StartBlob(Archive *AHX, Oid oid) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + if (!AH->StartBlobPtr) + fatal("large-object output not supported in chosen format"); + + AH->StartBlobPtr(AH, AH->currToc, oid); + + return 1; +} + +/* Called by a dumper to signal end of a BLOB */ +int +EndBlob(Archive *AHX, Oid oid) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + if (AH->EndBlobPtr) + AH->EndBlobPtr(AH, AH->currToc, oid); + + return 1; +} + +/********** + * BLOB Restoration + **********/ + +/* + * Called by a format handler before any blobs are restored + */ +void +StartRestoreBlobs(ArchiveHandle *AH) +{ + RestoreOptions *ropt = AH->public.ropt; + + if (!ropt->single_txn) + { + if (AH->connection) + StartTransaction(&AH->public); + else + ahprintf(AH, "BEGIN;\n\n"); + } + + AH->blobCount = 0; +} + +/* + * Called by a format handler after all blobs are restored + */ +void +EndRestoreBlobs(ArchiveHandle *AH) +{ + RestoreOptions *ropt = AH->public.ropt; + + if (!ropt->single_txn) + { + if (AH->connection) + CommitTransaction(&AH->public); + else + ahprintf(AH, "COMMIT;\n\n"); + } + + pg_log_info(ngettext("restored %d large object", + "restored %d large objects", + AH->blobCount), + AH->blobCount); +} + + +/* + * Called by a format handler to initiate restoration of a blob + */ +void +StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop) +{ + bool old_blob_style = (AH->version < K_VERS_1_12); + Oid loOid; + + AH->blobCount++; + + /* Initialize the LO Buffer */ + AH->lo_buf_used = 0; + + pg_log_info("restoring large object with OID %u", oid); + + /* With an old archive we must do drop and create logic here */ + if (old_blob_style && drop) + DropBlobIfExists(AH, oid); + + if (AH->connection) + { + if (old_blob_style) + { + loOid = lo_create(AH->connection, oid); + if (loOid == 0 || loOid != oid) + fatal("could not create large object %u: %s", + oid, PQerrorMessage(AH->connection)); + } + AH->loFd = lo_open(AH->connection, oid, INV_WRITE); + if (AH->loFd == -1) + fatal("could not open large object %u: %s", + oid, PQerrorMessage(AH->connection)); + } + else + { + if (old_blob_style) + ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n", + oid, INV_WRITE); + else + ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n", + oid, INV_WRITE); + } + + AH->writingBlob = 1; +} + +void +EndRestoreBlob(ArchiveHandle *AH, Oid oid) +{ + if (AH->lo_buf_used > 0) + { + /* Write remaining bytes from the LO buffer */ + dump_lo_buf(AH); + } + + AH->writingBlob = 0; + + if (AH->connection) + { + lo_close(AH->connection, AH->loFd); + AH->loFd = -1; + } + else + { + ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n"); + } +} + +/*********** + * Sorting and Reordering + ***********/ + +void +SortTocFromFile(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + RestoreOptions *ropt = AH->public.ropt; + FILE *fh; + StringInfoData linebuf; + + /* Allocate space for the 'wanted' array, and init it */ + ropt->idWanted = (bool *) pg_malloc0(sizeof(bool) * AH->maxDumpId); + + /* Setup the file */ + fh = fopen(ropt->tocFile, PG_BINARY_R); + if (!fh) + fatal("could not open TOC file \"%s\": %m", ropt->tocFile); + + initStringInfo(&linebuf); + + while (pg_get_line_buf(fh, &linebuf)) + { + char *cmnt; + char *endptr; + DumpId id; + TocEntry *te; + + /* Truncate line at comment, if any */ + cmnt = strchr(linebuf.data, ';'); + if (cmnt != NULL) + { + cmnt[0] = '\0'; + linebuf.len = cmnt - linebuf.data; + } + + /* Ignore if all blank */ + if (strspn(linebuf.data, " \t\r\n") == linebuf.len) + continue; + + /* Get an ID, check it's valid and not already seen */ + id = strtol(linebuf.data, &endptr, 10); + if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId || + ropt->idWanted[id - 1]) + { + pg_log_warning("line ignored: %s", linebuf.data); + continue; + } + + /* Find TOC entry */ + te = getTocEntryByDumpId(AH, id); + if (!te) + fatal("could not find entry for ID %d", + id); + + /* Mark it wanted */ + ropt->idWanted[id - 1] = true; + + /* + * Move each item to the end of the list as it is selected, so that + * they are placed in the desired order. Any unwanted items will end + * up at the front of the list, which may seem unintuitive but it's + * what we need. In an ordinary serial restore that makes no + * difference, but in a parallel restore we need to mark unrestored + * items' dependencies as satisfied before we start examining + * restorable items. Otherwise they could have surprising + * side-effects on the order in which restorable items actually get + * restored. + */ + _moveBefore(AH->toc, te); + } + + pg_free(linebuf.data); + + if (fclose(fh) != 0) + fatal("could not close TOC file: %m"); +} + +/********************** + * Convenience functions that look like standard IO functions + * for writing data when in dump mode. + **********************/ + +/* Public */ +void +archputs(const char *s, Archive *AH) +{ + WriteData(AH, s, strlen(s)); +} + +/* Public */ +int +archprintf(Archive *AH, const char *fmt,...) +{ + int save_errno = errno; + char *p; + size_t len = 128; /* initial assumption about buffer size */ + size_t cnt; + + for (;;) + { + va_list args; + + /* Allocate work buffer. */ + p = (char *) pg_malloc(len); + + /* Try to format the data. */ + errno = save_errno; + va_start(args, fmt); + cnt = pvsnprintf(p, len, fmt, args); + va_end(args); + + if (cnt < len) + break; /* success */ + + /* Release buffer and loop around to try again with larger len. */ + free(p); + len = cnt; + } + + WriteData(AH, p, cnt); + free(p); + return (int) cnt; +} + + +/******************************* + * Stuff below here should be 'private' to the archiver routines + *******************************/ + +static void +SetOutput(ArchiveHandle *AH, const char *filename, int compression) +{ + int fn; + + if (filename) + { + if (strcmp(filename, "-") == 0) + fn = fileno(stdout); + else + fn = -1; + } + else if (AH->FH) + fn = fileno(AH->FH); + else if (AH->fSpec) + { + fn = -1; + filename = AH->fSpec; + } + else + fn = fileno(stdout); + + /* If compression explicitly requested, use gzopen */ +#ifdef HAVE_LIBZ + if (compression != 0) + { + char fmode[14]; + + /* Don't use PG_BINARY_x since this is zlib */ + sprintf(fmode, "wb%d", compression); + if (fn >= 0) + AH->OF = gzdopen(dup(fn), fmode); + else + AH->OF = gzopen(filename, fmode); + AH->gzOut = 1; + } + else +#endif + { /* Use fopen */ + if (AH->mode == archModeAppend) + { + if (fn >= 0) + AH->OF = fdopen(dup(fn), PG_BINARY_A); + else + AH->OF = fopen(filename, PG_BINARY_A); + } + else + { + if (fn >= 0) + AH->OF = fdopen(dup(fn), PG_BINARY_W); + else + AH->OF = fopen(filename, PG_BINARY_W); + } + AH->gzOut = 0; + } + + if (!AH->OF) + { + if (filename) + fatal("could not open output file \"%s\": %m", filename); + else + fatal("could not open output file: %m"); + } +} + +static OutputContext +SaveOutput(ArchiveHandle *AH) +{ + OutputContext sav; + + sav.OF = AH->OF; + sav.gzOut = AH->gzOut; + + return sav; +} + +static void +RestoreOutput(ArchiveHandle *AH, OutputContext savedContext) +{ + int res; + + errno = 0; /* in case gzclose() doesn't set it */ + if (AH->gzOut) + res = GZCLOSE(AH->OF); + else + res = fclose(AH->OF); + + if (res != 0) + fatal("could not close output file: %m"); + + AH->gzOut = savedContext.gzOut; + AH->OF = savedContext.OF; +} + + + +/* + * Print formatted text to the output file (usually stdout). + */ +int +ahprintf(ArchiveHandle *AH, const char *fmt,...) +{ + int save_errno = errno; + char *p; + size_t len = 128; /* initial assumption about buffer size */ + size_t cnt; + + for (;;) + { + va_list args; + + /* Allocate work buffer. */ + p = (char *) pg_malloc(len); + + /* Try to format the data. */ + errno = save_errno; + va_start(args, fmt); + cnt = pvsnprintf(p, len, fmt, args); + va_end(args); + + if (cnt < len) + break; /* success */ + + /* Release buffer and loop around to try again with larger len. */ + free(p); + len = cnt; + } + + ahwrite(p, 1, cnt, AH); + free(p); + return (int) cnt; +} + +/* + * Single place for logic which says 'We are restoring to a direct DB connection'. + */ +static int +RestoringToDB(ArchiveHandle *AH) +{ + RestoreOptions *ropt = AH->public.ropt; + + return (ropt && ropt->useDB && AH->connection); +} + +/* + * Dump the current contents of the LO data buffer while writing a BLOB + */ +static void +dump_lo_buf(ArchiveHandle *AH) +{ + if (AH->connection) + { + int res; + + res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used); + pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)", + "wrote %zu bytes of large object data (result = %d)", + AH->lo_buf_used), + AH->lo_buf_used, res); + /* We assume there are no short writes, only errors */ + if (res != AH->lo_buf_used) + warn_or_exit_horribly(AH, "could not write to large object: %s", + PQerrorMessage(AH->connection)); + } + else + { + PQExpBuffer buf = createPQExpBuffer(); + + appendByteaLiteralAHX(buf, + (const unsigned char *) AH->lo_buf, + AH->lo_buf_used, + AH); + + /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */ + AH->writingBlob = 0; + ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data); + AH->writingBlob = 1; + + destroyPQExpBuffer(buf); + } + AH->lo_buf_used = 0; +} + + +/* + * Write buffer to the output file (usually stdout). This is used for + * outputting 'restore' scripts etc. It is even possible for an archive + * format to create a custom output routine to 'fake' a restore if it + * wants to generate a script (see TAR output). + */ +void +ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH) +{ + int bytes_written = 0; + + if (AH->writingBlob) + { + size_t remaining = size * nmemb; + + while (AH->lo_buf_used + remaining > AH->lo_buf_size) + { + size_t avail = AH->lo_buf_size - AH->lo_buf_used; + + memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail); + ptr = (const void *) ((const char *) ptr + avail); + remaining -= avail; + AH->lo_buf_used += avail; + dump_lo_buf(AH); + } + + memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining); + AH->lo_buf_used += remaining; + + bytes_written = size * nmemb; + } + else if (AH->gzOut) + bytes_written = GZWRITE(ptr, size, nmemb, AH->OF); + else if (AH->CustomOutPtr) + bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb); + + else + { + /* + * If we're doing a restore, and it's direct to DB, and we're + * connected then send it to the DB. + */ + if (RestoringToDB(AH)) + bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb); + else + bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size; + } + + if (bytes_written != size * nmemb) + WRITE_ERROR_EXIT; +} + +/* on some error, we may decide to go on... */ +void +warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...) +{ + va_list ap; + + switch (AH->stage) + { + + case STAGE_NONE: + /* Do nothing special */ + break; + + case STAGE_INITIALIZING: + if (AH->stage != AH->lastErrorStage) + pg_log_generic(PG_LOG_INFO, "while INITIALIZING:"); + break; + + case STAGE_PROCESSING: + if (AH->stage != AH->lastErrorStage) + pg_log_generic(PG_LOG_INFO, "while PROCESSING TOC:"); + break; + + case STAGE_FINALIZING: + if (AH->stage != AH->lastErrorStage) + pg_log_generic(PG_LOG_INFO, "while FINALIZING:"); + break; + } + if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE) + { + pg_log_generic(PG_LOG_INFO, "from TOC entry %d; %u %u %s %s %s", + AH->currentTE->dumpId, + AH->currentTE->catalogId.tableoid, + AH->currentTE->catalogId.oid, + AH->currentTE->desc ? AH->currentTE->desc : "(no desc)", + AH->currentTE->tag ? AH->currentTE->tag : "(no tag)", + AH->currentTE->owner ? AH->currentTE->owner : "(no owner)"); + } + AH->lastErrorStage = AH->stage; + AH->lastErrorTE = AH->currentTE; + + va_start(ap, fmt); + pg_log_generic_v(PG_LOG_ERROR, fmt, ap); + va_end(ap); + + if (AH->public.exit_on_error) + exit_nicely(1); + else + AH->public.n_errors++; +} + +#ifdef NOT_USED + +static void +_moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te) +{ + /* Unlink te from list */ + te->prev->next = te->next; + te->next->prev = te->prev; + + /* and insert it after "pos" */ + te->prev = pos; + te->next = pos->next; + pos->next->prev = te; + pos->next = te; +} +#endif + +static void +_moveBefore(TocEntry *pos, TocEntry *te) +{ + /* Unlink te from list */ + te->prev->next = te->next; + te->next->prev = te->prev; + + /* and insert it before "pos" */ + te->prev = pos->prev; + te->next = pos; + pos->prev->next = te; + pos->prev = te; +} + +/* + * Build index arrays for the TOC list + * + * This should be invoked only after we have created or read in all the TOC + * items. + * + * The arrays are indexed by dump ID (so entry zero is unused). Note that the + * array entries run only up to maxDumpId. We might see dependency dump IDs + * beyond that (if the dump was partial); so always check the array bound + * before trying to touch an array entry. + */ +static void +buildTocEntryArrays(ArchiveHandle *AH) +{ + DumpId maxDumpId = AH->maxDumpId; + TocEntry *te; + + AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *)); + AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId)); + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + /* this check is purely paranoia, maxDumpId should be correct */ + if (te->dumpId <= 0 || te->dumpId > maxDumpId) + fatal("bad dumpId"); + + /* tocsByDumpId indexes all TOCs by their dump ID */ + AH->tocsByDumpId[te->dumpId] = te; + + /* + * tableDataId provides the TABLE DATA item's dump ID for each TABLE + * TOC entry that has a DATA item. We compute this by reversing the + * TABLE DATA item's dependency, knowing that a TABLE DATA item has + * just one dependency and it is the TABLE item. + */ + if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0) + { + DumpId tableId = te->dependencies[0]; + + /* + * The TABLE item might not have been in the archive, if this was + * a data-only dump; but its dump ID should be less than its data + * item's dump ID, so there should be a place for it in the array. + */ + if (tableId <= 0 || tableId > maxDumpId) + fatal("bad table dumpId for TABLE DATA item"); + + AH->tableDataId[tableId] = te->dumpId; + } + } +} + +TocEntry * +getTocEntryByDumpId(ArchiveHandle *AH, DumpId id) +{ + /* build index arrays if we didn't already */ + if (AH->tocsByDumpId == NULL) + buildTocEntryArrays(AH); + + if (id > 0 && id <= AH->maxDumpId) + return AH->tocsByDumpId[id]; + + return NULL; +} + +int +TocIDRequired(ArchiveHandle *AH, DumpId id) +{ + TocEntry *te = getTocEntryByDumpId(AH, id); + + if (!te) + return 0; + + return te->reqs; +} + +size_t +WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet) +{ + int off; + + /* Save the flag */ + AH->WriteBytePtr(AH, wasSet); + + /* Write out pgoff_t smallest byte first, prevents endian mismatch */ + for (off = 0; off < sizeof(pgoff_t); off++) + { + AH->WriteBytePtr(AH, o & 0xFF); + o >>= 8; + } + return sizeof(pgoff_t) + 1; +} + +int +ReadOffset(ArchiveHandle *AH, pgoff_t * o) +{ + int i; + int off; + int offsetFlg; + + /* Initialize to zero */ + *o = 0; + + /* Check for old version */ + if (AH->version < K_VERS_1_7) + { + /* Prior versions wrote offsets using WriteInt */ + i = ReadInt(AH); + /* -1 means not set */ + if (i < 0) + return K_OFFSET_POS_NOT_SET; + else if (i == 0) + return K_OFFSET_NO_DATA; + + /* Cast to pgoff_t because it was written as an int. */ + *o = (pgoff_t) i; + return K_OFFSET_POS_SET; + } + + /* + * Read the flag indicating the state of the data pointer. Check if valid + * and die if not. + * + * This used to be handled by a negative or zero pointer, now we use an + * extra byte specifically for the state. + */ + offsetFlg = AH->ReadBytePtr(AH) & 0xFF; + + switch (offsetFlg) + { + case K_OFFSET_POS_NOT_SET: + case K_OFFSET_NO_DATA: + case K_OFFSET_POS_SET: + + break; + + default: + fatal("unexpected data offset flag %d", offsetFlg); + } + + /* + * Read the bytes + */ + for (off = 0; off < AH->offSize; off++) + { + if (off < sizeof(pgoff_t)) + *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8); + else + { + if (AH->ReadBytePtr(AH) != 0) + fatal("file offset in dump file is too large"); + } + } + + return offsetFlg; +} + +size_t +WriteInt(ArchiveHandle *AH, int i) +{ + int b; + + /* + * This is a bit yucky, but I don't want to make the binary format very + * dependent on representation, and not knowing much about it, I write out + * a sign byte. If you change this, don't forget to change the file + * version #, and modify ReadInt to read the new format AS WELL AS the old + * formats. + */ + + /* SIGN byte */ + if (i < 0) + { + AH->WriteBytePtr(AH, 1); + i = -i; + } + else + AH->WriteBytePtr(AH, 0); + + for (b = 0; b < AH->intSize; b++) + { + AH->WriteBytePtr(AH, i & 0xFF); + i >>= 8; + } + + return AH->intSize + 1; +} + +int +ReadInt(ArchiveHandle *AH) +{ + int res = 0; + int bv, + b; + int sign = 0; /* Default positive */ + int bitShift = 0; + + if (AH->version > K_VERS_1_0) + /* Read a sign byte */ + sign = AH->ReadBytePtr(AH); + + for (b = 0; b < AH->intSize; b++) + { + bv = AH->ReadBytePtr(AH) & 0xFF; + if (bv != 0) + res = res + (bv << bitShift); + bitShift += 8; + } + + if (sign) + res = -res; + + return res; +} + +size_t +WriteStr(ArchiveHandle *AH, const char *c) +{ + size_t res; + + if (c) + { + int len = strlen(c); + + res = WriteInt(AH, len); + AH->WriteBufPtr(AH, c, len); + res += len; + } + else + res = WriteInt(AH, -1); + + return res; +} + +char * +ReadStr(ArchiveHandle *AH) +{ + char *buf; + int l; + + l = ReadInt(AH); + if (l < 0) + buf = NULL; + else + { + buf = (char *) pg_malloc(l + 1); + AH->ReadBufPtr(AH, (void *) buf, l); + + buf[l] = '\0'; + } + + return buf; +} + +static int +_discoverArchiveFormat(ArchiveHandle *AH) +{ + FILE *fh; + char sig[6]; /* More than enough */ + size_t cnt; + int wantClose = 0; + + pg_log_debug("attempting to ascertain archive format"); + + if (AH->lookahead) + free(AH->lookahead); + + AH->readHeader = 0; + AH->lookaheadSize = 512; + AH->lookahead = pg_malloc0(512); + AH->lookaheadLen = 0; + AH->lookaheadPos = 0; + + if (AH->fSpec) + { + struct stat st; + + wantClose = 1; + + /* + * Check if the specified archive is a directory. If so, check if + * there's a "toc.dat" (or "toc.dat.gz") file in it. + */ + if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode)) + { + char buf[MAXPGPATH]; + + if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH) + fatal("directory name too long: \"%s\"", + AH->fSpec); + if (stat(buf, &st) == 0 && S_ISREG(st.st_mode)) + { + AH->format = archDirectory; + return AH->format; + } + +#ifdef HAVE_LIBZ + if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH) + fatal("directory name too long: \"%s\"", + AH->fSpec); + if (stat(buf, &st) == 0 && S_ISREG(st.st_mode)) + { + AH->format = archDirectory; + return AH->format; + } +#endif + fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)", + AH->fSpec); + fh = NULL; /* keep compiler quiet */ + } + else + { + fh = fopen(AH->fSpec, PG_BINARY_R); + if (!fh) + fatal("could not open input file \"%s\": %m", AH->fSpec); + } + } + else + { + fh = stdin; + if (!fh) + fatal("could not open input file: %m"); + } + + if ((cnt = fread(sig, 1, 5, fh)) != 5) + { + if (ferror(fh)) + fatal("could not read input file: %m"); + else + fatal("input file is too short (read %lu, expected 5)", + (unsigned long) cnt); + } + + /* Save it, just in case we need it later */ + memcpy(&AH->lookahead[0], sig, 5); + AH->lookaheadLen = 5; + + if (strncmp(sig, "PGDMP", 5) == 0) + { + /* It's custom format, stop here */ + AH->format = archCustom; + AH->readHeader = 1; + } + else + { + /* + * *Maybe* we have a tar archive format file or a text dump ... So, + * read first 512 byte header... + */ + cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh); + /* read failure is checked below */ + AH->lookaheadLen += cnt; + + if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) && + (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 || + strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0)) + { + /* + * looks like it's probably a text format dump. so suggest they + * try psql + */ + fatal("input file appears to be a text format dump. Please use psql."); + } + + if (AH->lookaheadLen != 512) + { + if (feof(fh)) + fatal("input file does not appear to be a valid archive (too short?)"); + else + READ_ERROR_EXIT(fh); + } + + if (!isValidTarHeader(AH->lookahead)) + fatal("input file does not appear to be a valid archive"); + + AH->format = archTar; + } + + /* Close the file if we opened it */ + if (wantClose) + { + if (fclose(fh) != 0) + fatal("could not close input file: %m"); + /* Forget lookahead, since we'll re-read header after re-opening */ + AH->readHeader = 0; + AH->lookaheadLen = 0; + } + + return AH->format; +} + + +/* + * Allocate an archive handle + */ +static ArchiveHandle * +_allocAH(const char *FileSpec, const ArchiveFormat fmt, + const int compression, bool dosync, ArchiveMode mode, + SetupWorkerPtrType setupWorkerPtr) +{ + ArchiveHandle *AH; + + pg_log_debug("allocating AH for %s, format %d", + FileSpec ? FileSpec : "(stdio)", fmt); + + AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle)); + + AH->version = K_VERS_SELF; + + /* initialize for backwards compatible string processing */ + AH->public.encoding = 0; /* PG_SQL_ASCII */ + AH->public.std_strings = false; + + /* sql error handling */ + AH->public.exit_on_error = true; + AH->public.n_errors = 0; + + AH->archiveDumpVersion = PG_VERSION; + + AH->createDate = time(NULL); + + AH->intSize = sizeof(int); + AH->offSize = sizeof(pgoff_t); + if (FileSpec) + { + AH->fSpec = pg_strdup(FileSpec); + + /* + * Not used; maybe later.... + * + * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ; + * i--) if (AH->workDir[i-1] == '/') + */ + } + else + AH->fSpec = NULL; + + AH->currUser = NULL; /* unknown */ + AH->currSchema = NULL; /* ditto */ + AH->currTablespace = NULL; /* ditto */ + AH->currTableAm = NULL; /* ditto */ + + AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry)); + + AH->toc->next = AH->toc; + AH->toc->prev = AH->toc; + + AH->mode = mode; + AH->compression = compression; + AH->dosync = dosync; + + memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse)); + + /* Open stdout with no compression for AH output handle */ + AH->gzOut = 0; + AH->OF = stdout; + + /* + * On Windows, we need to use binary mode to read/write non-text files, + * which include all archive formats as well as compressed plain text. + * Force stdin/stdout into binary mode if that is what we are using. + */ +#ifdef WIN32 + if ((fmt != archNull || compression != 0) && + (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)) + { + if (mode == archModeWrite) + _setmode(fileno(stdout), O_BINARY); + else + _setmode(fileno(stdin), O_BINARY); + } +#endif + + AH->SetupWorkerPtr = setupWorkerPtr; + + if (fmt == archUnknown) + AH->format = _discoverArchiveFormat(AH); + else + AH->format = fmt; + + switch (AH->format) + { + case archCustom: + InitArchiveFmt_Custom(AH); + break; + + case archNull: + InitArchiveFmt_Null(AH); + break; + + case archDirectory: + InitArchiveFmt_Directory(AH); + break; + + case archTar: + InitArchiveFmt_Tar(AH); + break; + + default: + fatal("unrecognized file format \"%d\"", fmt); + } + + return AH; +} + +/* + * Write out all data (tables & blobs) + */ +void +WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate) +{ + TocEntry *te; + + if (pstate && pstate->numWorkers > 1) + { + /* + * In parallel mode, this code runs in the leader process. We + * construct an array of candidate TEs, then sort it into decreasing + * size order, then dispatch each TE to a data-transfer worker. By + * dumping larger tables first, we avoid getting into a situation + * where we're down to one job and it's big, losing parallelism. + */ + TocEntry **tes; + int ntes; + + tes = (TocEntry **) pg_malloc(AH->tocCount * sizeof(TocEntry *)); + ntes = 0; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + /* Consider only TEs with dataDumper functions ... */ + if (!te->dataDumper) + continue; + /* ... and ignore ones not enabled for dump */ + if ((te->reqs & REQ_DATA) == 0) + continue; + + tes[ntes++] = te; + } + + if (ntes > 1) + qsort((void *) tes, ntes, sizeof(TocEntry *), + TocEntrySizeCompare); + + for (int i = 0; i < ntes; i++) + DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP, + mark_dump_job_done, NULL); + + pg_free(tes); + + /* Now wait for workers to finish. */ + WaitForWorkers(AH, pstate, WFW_ALL_IDLE); + } + else + { + /* Non-parallel mode: just dump all candidate TEs sequentially. */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + /* Must have same filter conditions as above */ + if (!te->dataDumper) + continue; + if ((te->reqs & REQ_DATA) == 0) + continue; + + WriteDataChunksForTocEntry(AH, te); + } + } +} + + +/* + * Callback function that's invoked in the leader process after a step has + * been parallel dumped. + * + * We don't need to do anything except check for worker failure. + */ +static void +mark_dump_job_done(ArchiveHandle *AH, + TocEntry *te, + int status, + void *callback_data) +{ + pg_log_info("finished item %d %s %s", + te->dumpId, te->desc, te->tag); + + if (status != 0) + fatal("worker process failed: exit code %d", + status); +} + + +void +WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te) +{ + StartDataPtrType startPtr; + EndDataPtrType endPtr; + + AH->currToc = te; + + if (strcmp(te->desc, "BLOBS") == 0) + { + startPtr = AH->StartBlobsPtr; + endPtr = AH->EndBlobsPtr; + } + else + { + startPtr = AH->StartDataPtr; + endPtr = AH->EndDataPtr; + } + + if (startPtr != NULL) + (*startPtr) (AH, te); + + /* + * The user-provided DataDumper routine needs to call AH->WriteData + */ + te->dataDumper((Archive *) AH, te->dataDumperArg); + + if (endPtr != NULL) + (*endPtr) (AH, te); + + AH->currToc = NULL; +} + +void +WriteToc(ArchiveHandle *AH) +{ + TocEntry *te; + char workbuf[32]; + int tocCount; + int i; + + /* count entries that will actually be dumped */ + tocCount = 0; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0) + tocCount++; + } + + /* printf("%d TOC Entries to save\n", tocCount); */ + + WriteInt(AH, tocCount); + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0) + continue; + + WriteInt(AH, te->dumpId); + WriteInt(AH, te->dataDumper ? 1 : 0); + + /* OID is recorded as a string for historical reasons */ + sprintf(workbuf, "%u", te->catalogId.tableoid); + WriteStr(AH, workbuf); + sprintf(workbuf, "%u", te->catalogId.oid); + WriteStr(AH, workbuf); + + WriteStr(AH, te->tag); + WriteStr(AH, te->desc); + WriteInt(AH, te->section); + WriteStr(AH, te->defn); + WriteStr(AH, te->dropStmt); + WriteStr(AH, te->copyStmt); + WriteStr(AH, te->namespace); + WriteStr(AH, te->tablespace); + WriteStr(AH, te->tableam); + WriteStr(AH, te->owner); + WriteStr(AH, "false"); + + /* Dump list of dependencies */ + for (i = 0; i < te->nDeps; i++) + { + sprintf(workbuf, "%d", te->dependencies[i]); + WriteStr(AH, workbuf); + } + WriteStr(AH, NULL); /* Terminate List */ + + if (AH->WriteExtraTocPtr) + AH->WriteExtraTocPtr(AH, te); + } +} + +void +ReadToc(ArchiveHandle *AH) +{ + int i; + char *tmp; + DumpId *deps; + int depIdx; + int depSize; + TocEntry *te; + + AH->tocCount = ReadInt(AH); + AH->maxDumpId = 0; + + for (i = 0; i < AH->tocCount; i++) + { + te = (TocEntry *) pg_malloc0(sizeof(TocEntry)); + te->dumpId = ReadInt(AH); + + if (te->dumpId > AH->maxDumpId) + AH->maxDumpId = te->dumpId; + + /* Sanity check */ + if (te->dumpId <= 0) + fatal("entry ID %d out of range -- perhaps a corrupt TOC", + te->dumpId); + + te->hadDumper = ReadInt(AH); + + if (AH->version >= K_VERS_1_8) + { + tmp = ReadStr(AH); + sscanf(tmp, "%u", &te->catalogId.tableoid); + free(tmp); + } + else + te->catalogId.tableoid = InvalidOid; + tmp = ReadStr(AH); + sscanf(tmp, "%u", &te->catalogId.oid); + free(tmp); + + te->tag = ReadStr(AH); + te->desc = ReadStr(AH); + + if (AH->version >= K_VERS_1_11) + { + te->section = ReadInt(AH); + } + else + { + /* + * Rules for pre-8.4 archives wherein pg_dump hasn't classified + * the entries into sections. This list need not cover entry + * types added later than 8.4. + */ + if (strcmp(te->desc, "COMMENT") == 0 || + strcmp(te->desc, "ACL") == 0 || + strcmp(te->desc, "ACL LANGUAGE") == 0) + te->section = SECTION_NONE; + else if (strcmp(te->desc, "TABLE DATA") == 0 || + strcmp(te->desc, "BLOBS") == 0 || + strcmp(te->desc, "BLOB COMMENTS") == 0) + te->section = SECTION_DATA; + else if (strcmp(te->desc, "CONSTRAINT") == 0 || + strcmp(te->desc, "CHECK CONSTRAINT") == 0 || + strcmp(te->desc, "FK CONSTRAINT") == 0 || + strcmp(te->desc, "INDEX") == 0 || + strcmp(te->desc, "RULE") == 0 || + strcmp(te->desc, "TRIGGER") == 0) + te->section = SECTION_POST_DATA; + else + te->section = SECTION_PRE_DATA; + } + + te->defn = ReadStr(AH); + te->dropStmt = ReadStr(AH); + + if (AH->version >= K_VERS_1_3) + te->copyStmt = ReadStr(AH); + + if (AH->version >= K_VERS_1_6) + te->namespace = ReadStr(AH); + + if (AH->version >= K_VERS_1_10) + te->tablespace = ReadStr(AH); + + if (AH->version >= K_VERS_1_14) + te->tableam = ReadStr(AH); + + te->owner = ReadStr(AH); + if (AH->version < K_VERS_1_9 || strcmp(ReadStr(AH), "true") == 0) + pg_log_warning("restoring tables WITH OIDS is not supported anymore"); + + /* Read TOC entry dependencies */ + if (AH->version >= K_VERS_1_5) + { + depSize = 100; + deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize); + depIdx = 0; + for (;;) + { + tmp = ReadStr(AH); + if (!tmp) + break; /* end of list */ + if (depIdx >= depSize) + { + depSize *= 2; + deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize); + } + sscanf(tmp, "%d", &deps[depIdx]); + free(tmp); + depIdx++; + } + + if (depIdx > 0) /* We have a non-null entry */ + { + deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx); + te->dependencies = deps; + te->nDeps = depIdx; + } + else + { + free(deps); + te->dependencies = NULL; + te->nDeps = 0; + } + } + else + { + te->dependencies = NULL; + te->nDeps = 0; + } + te->dataLength = 0; + + if (AH->ReadExtraTocPtr) + AH->ReadExtraTocPtr(AH, te); + + pg_log_debug("read TOC entry %d (ID %d) for %s %s", + i, te->dumpId, te->desc, te->tag); + + /* link completed entry into TOC circular list */ + te->prev = AH->toc->prev; + AH->toc->prev->next = te; + AH->toc->prev = te; + te->next = AH->toc; + + /* special processing immediately upon read for some items */ + if (strcmp(te->desc, "ENCODING") == 0) + processEncodingEntry(AH, te); + else if (strcmp(te->desc, "STDSTRINGS") == 0) + processStdStringsEntry(AH, te); + else if (strcmp(te->desc, "SEARCHPATH") == 0) + processSearchPathEntry(AH, te); + } +} + +static void +processEncodingEntry(ArchiveHandle *AH, TocEntry *te) +{ + /* te->defn should have the form SET client_encoding = 'foo'; */ + char *defn = pg_strdup(te->defn); + char *ptr1; + char *ptr2 = NULL; + int encoding; + + ptr1 = strchr(defn, '\''); + if (ptr1) + ptr2 = strchr(++ptr1, '\''); + if (ptr2) + { + *ptr2 = '\0'; + encoding = pg_char_to_encoding(ptr1); + if (encoding < 0) + fatal("unrecognized encoding \"%s\"", + ptr1); + AH->public.encoding = encoding; + } + else + fatal("invalid ENCODING item: %s", + te->defn); + + free(defn); +} + +static void +processStdStringsEntry(ArchiveHandle *AH, TocEntry *te) +{ + /* te->defn should have the form SET standard_conforming_strings = 'x'; */ + char *ptr1; + + ptr1 = strchr(te->defn, '\''); + if (ptr1 && strncmp(ptr1, "'on'", 4) == 0) + AH->public.std_strings = true; + else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0) + AH->public.std_strings = false; + else + fatal("invalid STDSTRINGS item: %s", + te->defn); +} + +static void +processSearchPathEntry(ArchiveHandle *AH, TocEntry *te) +{ + /* + * te->defn should contain a command to set search_path. We just copy it + * verbatim for use later. + */ + AH->public.searchpath = pg_strdup(te->defn); +} + +static void +StrictNamesCheck(RestoreOptions *ropt) +{ + const char *missing_name; + + Assert(ropt->strict_names); + + if (ropt->schemaNames.head != NULL) + { + missing_name = simple_string_list_not_touched(&ropt->schemaNames); + if (missing_name != NULL) + fatal("schema \"%s\" not found", missing_name); + } + + if (ropt->tableNames.head != NULL) + { + missing_name = simple_string_list_not_touched(&ropt->tableNames); + if (missing_name != NULL) + fatal("table \"%s\" not found", missing_name); + } + + if (ropt->indexNames.head != NULL) + { + missing_name = simple_string_list_not_touched(&ropt->indexNames); + if (missing_name != NULL) + fatal("index \"%s\" not found", missing_name); + } + + if (ropt->functionNames.head != NULL) + { + missing_name = simple_string_list_not_touched(&ropt->functionNames); + if (missing_name != NULL) + fatal("function \"%s\" not found", missing_name); + } + + if (ropt->triggerNames.head != NULL) + { + missing_name = simple_string_list_not_touched(&ropt->triggerNames); + if (missing_name != NULL) + fatal("trigger \"%s\" not found", missing_name); + } +} + +/* + * Determine whether we want to restore this TOC entry. + * + * Returns 0 if entry should be skipped, or some combination of the + * REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data + * portions of this TOC entry, or REQ_SPECIAL if it's a special entry. + */ +static int +_tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) +{ + int res = REQ_SCHEMA | REQ_DATA; + RestoreOptions *ropt = AH->public.ropt; + + /* These items are treated specially */ + if (strcmp(te->desc, "ENCODING") == 0 || + strcmp(te->desc, "STDSTRINGS") == 0 || + strcmp(te->desc, "SEARCHPATH") == 0) + return REQ_SPECIAL; + + /* + * DATABASE and DATABASE PROPERTIES also have a special rule: they are + * restored in createDB mode, and not restored otherwise, independently of + * all else. + */ + if (strcmp(te->desc, "DATABASE") == 0 || + strcmp(te->desc, "DATABASE PROPERTIES") == 0) + { + if (ropt->createDB) + return REQ_SCHEMA; + else + return 0; + } + + /* + * Process exclusions that affect certain classes of TOC entries. + */ + + /* If it's an ACL, maybe ignore it */ + if (ropt->aclsSkip && _tocEntryIsACL(te)) + return 0; + + /* If it's a comment, maybe ignore it */ + if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0) + return 0; + + /* + * If it's a publication or a table part of a publication, maybe ignore + * it. + */ + if (ropt->no_publications && + (strcmp(te->desc, "PUBLICATION") == 0 || + strcmp(te->desc, "PUBLICATION TABLE") == 0)) + return 0; + + /* If it's a security label, maybe ignore it */ + if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0) + return 0; + + /* If it's a subscription, maybe ignore it */ + if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0) + return 0; + + /* Ignore it if section is not to be dumped/restored */ + switch (curSection) + { + case SECTION_PRE_DATA: + if (!(ropt->dumpSections & DUMP_PRE_DATA)) + return 0; + break; + case SECTION_DATA: + if (!(ropt->dumpSections & DUMP_DATA)) + return 0; + break; + case SECTION_POST_DATA: + if (!(ropt->dumpSections & DUMP_POST_DATA)) + return 0; + break; + default: + /* shouldn't get here, really, but ignore it */ + return 0; + } + + /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */ + if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1]) + return 0; + + /* + * Check options for selective dump/restore. + */ + if (strcmp(te->desc, "ACL") == 0 || + strcmp(te->desc, "COMMENT") == 0 || + strcmp(te->desc, "SECURITY LABEL") == 0) + { + /* Database properties react to createDB, not selectivity options. */ + if (strncmp(te->tag, "DATABASE ", 9) == 0) + { + if (!ropt->createDB) + return 0; + } + else if (ropt->schemaNames.head != NULL || + ropt->schemaExcludeNames.head != NULL || + ropt->selTypes) + { + /* + * In a selective dump/restore, we want to restore these dependent + * TOC entry types only if their parent object is being restored. + * Without selectivity options, we let through everything in the + * archive. Note there may be such entries with no parent, eg + * non-default ACLs for built-in objects. + * + * This code depends on the parent having been marked already, + * which should be the case; if it isn't, perhaps due to + * SortTocFromFile rearrangement, skipping the dependent entry + * seems prudent anyway. + * + * Ideally we'd handle, eg, table CHECK constraints this way too. + * But it's hard to tell which of their dependencies is the one to + * consult. + */ + if (te->nDeps != 1 || + TocIDRequired(AH, te->dependencies[0]) == 0) + return 0; + } + } + else + { + /* Apply selective-restore rules for standalone TOC entries. */ + if (ropt->schemaNames.head != NULL) + { + /* If no namespace is specified, it means all. */ + if (!te->namespace) + return 0; + if (!simple_string_list_member(&ropt->schemaNames, te->namespace)) + return 0; + } + + if (ropt->schemaExcludeNames.head != NULL && + te->namespace && + simple_string_list_member(&ropt->schemaExcludeNames, te->namespace)) + return 0; + + if (ropt->selTypes) + { + if (strcmp(te->desc, "TABLE") == 0 || + strcmp(te->desc, "TABLE DATA") == 0 || + strcmp(te->desc, "VIEW") == 0 || + strcmp(te->desc, "FOREIGN TABLE") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 || + strcmp(te->desc, "SEQUENCE") == 0 || + strcmp(te->desc, "SEQUENCE SET") == 0) + { + if (!ropt->selTable) + return 0; + if (ropt->tableNames.head != NULL && + !simple_string_list_member(&ropt->tableNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "INDEX") == 0) + { + if (!ropt->selIndex) + return 0; + if (ropt->indexNames.head != NULL && + !simple_string_list_member(&ropt->indexNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "FUNCTION") == 0 || + strcmp(te->desc, "AGGREGATE") == 0 || + strcmp(te->desc, "PROCEDURE") == 0) + { + if (!ropt->selFunction) + return 0; + if (ropt->functionNames.head != NULL && + !simple_string_list_member(&ropt->functionNames, te->tag)) + return 0; + } + else if (strcmp(te->desc, "TRIGGER") == 0) + { + if (!ropt->selTrigger) + return 0; + if (ropt->triggerNames.head != NULL && + !simple_string_list_member(&ropt->triggerNames, te->tag)) + return 0; + } + else + return 0; + } + } + + /* + * Determine whether the TOC entry contains schema and/or data components, + * and mask off inapplicable REQ bits. If it had a dataDumper, assume + * it's both schema and data. Otherwise it's probably schema-only, but + * there are exceptions. + */ + if (!te->hadDumper) + { + /* + * Special Case: If 'SEQUENCE SET' or anything to do with BLOBs, then + * it is considered a data entry. We don't need to check for the + * BLOBS entry or old-style BLOB COMMENTS, because they will have + * hadDumper = true ... but we do need to check new-style BLOB ACLs, + * comments, etc. + */ + if (strcmp(te->desc, "SEQUENCE SET") == 0 || + strcmp(te->desc, "BLOB") == 0 || + (strcmp(te->desc, "ACL") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0) || + (strcmp(te->desc, "COMMENT") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0) || + (strcmp(te->desc, "SECURITY LABEL") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0)) + res = res & REQ_DATA; + else + res = res & ~REQ_DATA; + } + + /* If there's no definition command, there's no schema component */ + if (!te->defn || !te->defn[0]) + res = res & ~REQ_SCHEMA; + + /* + * Special case: type with tag; this is obsolete and we + * always ignore it. + */ + if ((strcmp(te->desc, "") == 0) && (strcmp(te->tag, "Max OID") == 0)) + return 0; + + /* Mask it if we only want schema */ + if (ropt->schemaOnly) + { + /* + * The sequence_data option overrides schemaOnly for SEQUENCE SET. + * + * In binary-upgrade mode, even with schemaOnly set, we do not mask + * out large objects. (Only large object definitions, comments and + * other metadata should be generated in binary-upgrade mode, not the + * actual data, but that need not concern us here.) + */ + if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) && + !(ropt->binary_upgrade && + (strcmp(te->desc, "BLOB") == 0 || + (strcmp(te->desc, "ACL") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0) || + (strcmp(te->desc, "COMMENT") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0) || + (strcmp(te->desc, "SECURITY LABEL") == 0 && + strncmp(te->tag, "LARGE OBJECT ", 13) == 0)))) + res = res & REQ_SCHEMA; + } + + /* Mask it if we only want data */ + if (ropt->dataOnly) + res = res & REQ_DATA; + + return res; +} + +/* + * Identify which pass we should restore this TOC entry in. + * + * See notes with the RestorePass typedef in pg_backup_archiver.h. + */ +static RestorePass +_tocEntryRestorePass(TocEntry *te) +{ + /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */ + if (strcmp(te->desc, "ACL") == 0 || + strcmp(te->desc, "ACL LANGUAGE") == 0 || + strcmp(te->desc, "DEFAULT ACL") == 0) + return RESTORE_PASS_ACL; + if (strcmp(te->desc, "EVENT TRIGGER") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0) + return RESTORE_PASS_POST_ACL; + + /* + * Comments need to be emitted in the same pass as their parent objects. + * ACLs haven't got comments, and neither do matview data objects, but + * event triggers do. (Fortunately, event triggers haven't got ACLs, or + * we'd need yet another weird special case.) + */ + if (strcmp(te->desc, "COMMENT") == 0 && + strncmp(te->tag, "EVENT TRIGGER ", 14) == 0) + return RESTORE_PASS_POST_ACL; + + /* All else can be handled in the main pass. */ + return RESTORE_PASS_MAIN; +} + +/* + * Identify TOC entries that are ACLs. + * + * Note: it seems worth duplicating some code here to avoid a hard-wired + * assumption that these are exactly the same entries that we restore during + * the RESTORE_PASS_ACL phase. + */ +static bool +_tocEntryIsACL(TocEntry *te) +{ + /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */ + if (strcmp(te->desc, "ACL") == 0 || + strcmp(te->desc, "ACL LANGUAGE") == 0 || + strcmp(te->desc, "DEFAULT ACL") == 0) + return true; + return false; +} + +/* + * Issue SET commands for parameters that we want to have set the same way + * at all times during execution of a restore script. + */ +static void +_doSetFixedOutputState(ArchiveHandle *AH) +{ + RestoreOptions *ropt = AH->public.ropt; + + /* + * Disable timeouts to allow for slow commands, idle parallel workers, etc + */ + ahprintf(AH, "SET statement_timeout = 0;\n"); + ahprintf(AH, "SET lock_timeout = 0;\n"); + ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n"); + + /* Select the correct character set encoding */ + ahprintf(AH, "SET client_encoding = '%s';\n", + pg_encoding_to_char(AH->public.encoding)); + + /* Select the correct string literal syntax */ + ahprintf(AH, "SET standard_conforming_strings = %s;\n", + AH->public.std_strings ? "on" : "off"); + + /* Select the role to be used during restore */ + if (ropt && ropt->use_role) + ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role)); + + /* Select the dump-time search_path */ + if (AH->public.searchpath) + ahprintf(AH, "%s", AH->public.searchpath); + + /* Make sure function checking is disabled */ + ahprintf(AH, "SET check_function_bodies = false;\n"); + + /* Ensure that all valid XML data will be accepted */ + ahprintf(AH, "SET xmloption = content;\n"); + + /* Avoid annoying notices etc */ + ahprintf(AH, "SET client_min_messages = warning;\n"); + if (!AH->public.std_strings) + ahprintf(AH, "SET escape_string_warning = off;\n"); + + /* Adjust row-security state */ + if (ropt && ropt->enable_row_security) + ahprintf(AH, "SET row_security = on;\n"); + else + ahprintf(AH, "SET row_security = off;\n"); + + ahprintf(AH, "\n"); +} + +/* + * Issue a SET SESSION AUTHORIZATION command. Caller is responsible + * for updating state if appropriate. If user is NULL or an empty string, + * the specification DEFAULT will be used. + */ +static void +_doSetSessionAuth(ArchiveHandle *AH, const char *user) +{ + PQExpBuffer cmd = createPQExpBuffer(); + + appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION "); + + /* + * SQL requires a string literal here. Might as well be correct. + */ + if (user && *user) + appendStringLiteralAHX(cmd, user, AH); + else + appendPQExpBufferStr(cmd, "DEFAULT"); + appendPQExpBufferChar(cmd, ';'); + + if (RestoringToDB(AH)) + { + PGresult *res; + + res = PQexec(AH->connection, cmd->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + /* NOT warn_or_exit_horribly... use -O instead to skip this. */ + fatal("could not set session user to \"%s\": %s", + user, PQerrorMessage(AH->connection)); + + PQclear(res); + } + else + ahprintf(AH, "%s\n\n", cmd->data); + + destroyPQExpBuffer(cmd); +} + + +/* + * Issue the commands to connect to the specified database. + * + * If we're currently restoring right into a database, this will + * actually establish a connection. Otherwise it puts a \connect into + * the script output. + */ +static void +_reconnectToDB(ArchiveHandle *AH, const char *dbname) +{ + if (RestoringToDB(AH)) + ReconnectToServer(AH, dbname); + else + { + PQExpBufferData connectbuf; + + initPQExpBuffer(&connectbuf); + appendPsqlMetaConnect(&connectbuf, dbname); + ahprintf(AH, "%s\n", connectbuf.data); + termPQExpBuffer(&connectbuf); + } + + /* + * NOTE: currUser keeps track of what the imaginary session user in our + * script is. It's now effectively reset to the original userID. + */ + if (AH->currUser) + free(AH->currUser); + AH->currUser = NULL; + + /* don't assume we still know the output schema, tablespace, etc either */ + if (AH->currSchema) + free(AH->currSchema); + AH->currSchema = NULL; + if (AH->currTablespace) + free(AH->currTablespace); + AH->currTablespace = NULL; + + /* re-establish fixed state */ + _doSetFixedOutputState(AH); +} + +/* + * Become the specified user, and update state to avoid redundant commands + * + * NULL or empty argument is taken to mean restoring the session default + */ +static void +_becomeUser(ArchiveHandle *AH, const char *user) +{ + if (!user) + user = ""; /* avoid null pointers */ + + if (AH->currUser && strcmp(AH->currUser, user) == 0) + return; /* no need to do anything */ + + _doSetSessionAuth(AH, user); + + /* + * NOTE: currUser keeps track of what the imaginary session user in our + * script is + */ + if (AH->currUser) + free(AH->currUser); + AH->currUser = pg_strdup(user); +} + +/* + * Become the owner of the given TOC entry object. If + * changes in ownership are not allowed, this doesn't do anything. + */ +static void +_becomeOwner(ArchiveHandle *AH, TocEntry *te) +{ + RestoreOptions *ropt = AH->public.ropt; + + if (ropt && (ropt->noOwner || !ropt->use_setsessauth)) + return; + + _becomeUser(AH, te->owner); +} + + +/* + * Issue the commands to select the specified schema as the current schema + * in the target database. + */ +static void +_selectOutputSchema(ArchiveHandle *AH, const char *schemaName) +{ + PQExpBuffer qry; + + /* + * If there was a SEARCHPATH TOC entry, we're supposed to just stay with + * that search_path rather than switching to entry-specific paths. + * Otherwise, it's an old archive that will not restore correctly unless + * we set the search_path as it's expecting. + */ + if (AH->public.searchpath) + return; + + if (!schemaName || *schemaName == '\0' || + (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0)) + return; /* no need to do anything */ + + qry = createPQExpBuffer(); + + appendPQExpBuffer(qry, "SET search_path = %s", + fmtId(schemaName)); + if (strcmp(schemaName, "pg_catalog") != 0) + appendPQExpBufferStr(qry, ", pg_catalog"); + + if (RestoringToDB(AH)) + { + PGresult *res; + + res = PQexec(AH->connection, qry->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + warn_or_exit_horribly(AH, + "could not set search_path to \"%s\": %s", + schemaName, PQerrorMessage(AH->connection)); + + PQclear(res); + } + else + ahprintf(AH, "%s;\n\n", qry->data); + + if (AH->currSchema) + free(AH->currSchema); + AH->currSchema = pg_strdup(schemaName); + + destroyPQExpBuffer(qry); +} + +/* + * Issue the commands to select the specified tablespace as the current one + * in the target database. + */ +static void +_selectTablespace(ArchiveHandle *AH, const char *tablespace) +{ + RestoreOptions *ropt = AH->public.ropt; + PQExpBuffer qry; + const char *want, + *have; + + /* do nothing in --no-tablespaces mode */ + if (ropt->noTablespace) + return; + + have = AH->currTablespace; + want = tablespace; + + /* no need to do anything for non-tablespace object */ + if (!want) + return; + + if (have && strcmp(want, have) == 0) + return; /* no need to do anything */ + + qry = createPQExpBuffer(); + + if (strcmp(want, "") == 0) + { + /* We want the tablespace to be the database's default */ + appendPQExpBufferStr(qry, "SET default_tablespace = ''"); + } + else + { + /* We want an explicit tablespace */ + appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want)); + } + + if (RestoringToDB(AH)) + { + PGresult *res; + + res = PQexec(AH->connection, qry->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + warn_or_exit_horribly(AH, + "could not set default_tablespace to %s: %s", + fmtId(want), PQerrorMessage(AH->connection)); + + PQclear(res); + } + else + ahprintf(AH, "%s;\n\n", qry->data); + + if (AH->currTablespace) + free(AH->currTablespace); + AH->currTablespace = pg_strdup(want); + + destroyPQExpBuffer(qry); +} + +/* + * Set the proper default_table_access_method value for the table. + */ +static void +_selectTableAccessMethod(ArchiveHandle *AH, const char *tableam) +{ + PQExpBuffer cmd; + const char *want, + *have; + + have = AH->currTableAm; + want = tableam; + + if (!want) + return; + + if (have && strcmp(want, have) == 0) + return; + + cmd = createPQExpBuffer(); + appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want)); + + if (RestoringToDB(AH)) + { + PGresult *res; + + res = PQexec(AH->connection, cmd->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + warn_or_exit_horribly(AH, + "could not set default_table_access_method: %s", + PQerrorMessage(AH->connection)); + + PQclear(res); + } + else + ahprintf(AH, "%s\n\n", cmd->data); + + destroyPQExpBuffer(cmd); + + AH->currTableAm = pg_strdup(want); +} + +/* + * Extract an object description for a TOC entry, and append it to buf. + * + * This is used for ALTER ... OWNER TO. + */ +static void +_getObjectDescription(PQExpBuffer buf, TocEntry *te) +{ + const char *type = te->desc; + + /* Use ALTER TABLE for views and sequences */ + if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "MATERIALIZED VIEW") == 0) + type = "TABLE"; + + /* objects that don't require special decoration */ + if (strcmp(type, "COLLATION") == 0 || + strcmp(type, "CONVERSION") == 0 || + strcmp(type, "DOMAIN") == 0 || + strcmp(type, "TABLE") == 0 || + strcmp(type, "TYPE") == 0 || + strcmp(type, "FOREIGN TABLE") == 0 || + strcmp(type, "TEXT SEARCH DICTIONARY") == 0 || + strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 || + strcmp(type, "STATISTICS") == 0 || + /* non-schema-specified objects */ + strcmp(type, "DATABASE") == 0 || + strcmp(type, "PROCEDURAL LANGUAGE") == 0 || + strcmp(type, "SCHEMA") == 0 || + strcmp(type, "EVENT TRIGGER") == 0 || + strcmp(type, "FOREIGN DATA WRAPPER") == 0 || + strcmp(type, "SERVER") == 0 || + strcmp(type, "PUBLICATION") == 0 || + strcmp(type, "SUBSCRIPTION") == 0 || + strcmp(type, "USER MAPPING") == 0) + { + appendPQExpBuffer(buf, "%s ", type); + if (te->namespace && *te->namespace) + appendPQExpBuffer(buf, "%s.", fmtId(te->namespace)); + appendPQExpBufferStr(buf, fmtId(te->tag)); + return; + } + + /* BLOBs just have a name, but it's numeric so must not use fmtId */ + if (strcmp(type, "BLOB") == 0) + { + appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag); + return; + } + + /* + * These object types require additional decoration. Fortunately, the + * information needed is exactly what's in the DROP command. + */ + if (strcmp(type, "AGGREGATE") == 0 || + strcmp(type, "FUNCTION") == 0 || + strcmp(type, "OPERATOR") == 0 || + strcmp(type, "OPERATOR CLASS") == 0 || + strcmp(type, "OPERATOR FAMILY") == 0 || + strcmp(type, "PROCEDURE") == 0) + { + /* Chop "DROP " off the front and make a modifiable copy */ + char *first = pg_strdup(te->dropStmt + 5); + char *last; + + /* point to last character in string */ + last = first + strlen(first) - 1; + + /* Strip off any ';' or '\n' at the end */ + while (last >= first && (*last == '\n' || *last == ';')) + last--; + *(last + 1) = '\0'; + + appendPQExpBufferStr(buf, first); + + free(first); + return; + } + + pg_log_warning("don't know how to set owner for object type \"%s\"", + type); +} + +/* + * Emit the SQL commands to create the object represented by a TOC entry + * + * This now also includes issuing an ALTER OWNER command to restore the + * object's ownership, if wanted. But note that the object's permissions + * will remain at default, until the matching ACL TOC entry is restored. + */ +static void +_printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) +{ + RestoreOptions *ropt = AH->public.ropt; + + /* Select owner, schema, tablespace and default AM as necessary */ + _becomeOwner(AH, te); + _selectOutputSchema(AH, te->namespace); + _selectTablespace(AH, te->tablespace); + _selectTableAccessMethod(AH, te->tableam); + + /* Emit header comment for item */ + if (!AH->noTocComments) + { + const char *pfx; + char *sanitized_name; + char *sanitized_schema; + char *sanitized_owner; + + if (isData) + pfx = "Data for "; + else + pfx = ""; + + ahprintf(AH, "--\n"); + if (AH->public.verbose) + { + ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n", + te->dumpId, te->catalogId.tableoid, te->catalogId.oid); + if (te->nDeps > 0) + { + int i; + + ahprintf(AH, "-- Dependencies:"); + for (i = 0; i < te->nDeps; i++) + ahprintf(AH, " %d", te->dependencies[i]); + ahprintf(AH, "\n"); + } + } + + sanitized_name = sanitize_line(te->tag, false); + sanitized_schema = sanitize_line(te->namespace, true); + sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true); + + ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s", + pfx, sanitized_name, te->desc, sanitized_schema, + sanitized_owner); + + free(sanitized_name); + free(sanitized_schema); + free(sanitized_owner); + + if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace) + { + char *sanitized_tablespace; + + sanitized_tablespace = sanitize_line(te->tablespace, false); + ahprintf(AH, "; Tablespace: %s", sanitized_tablespace); + free(sanitized_tablespace); + } + ahprintf(AH, "\n"); + + if (AH->PrintExtraTocPtr != NULL) + AH->PrintExtraTocPtr(AH, te); + ahprintf(AH, "--\n\n"); + } + + /* + * Actually print the definition. + * + * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump + * versions put into CREATE SCHEMA. We have to do this when --no-owner + * mode is selected. This is ugly, but I see no other good way ... + */ + if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0) + { + ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag)); + } + else + { + if (te->defn && strlen(te->defn) > 0) + ahprintf(AH, "%s\n\n", te->defn); + } + + /* + * If we aren't using SET SESSION AUTH to determine ownership, we must + * instead issue an ALTER OWNER command. We assume that anything without + * a DROP command is not a separately ownable object. All the categories + * with DROP commands must appear in one list or the other. + */ + if (!ropt->noOwner && !ropt->use_setsessauth && + te->owner && strlen(te->owner) > 0 && + te->dropStmt && strlen(te->dropStmt) > 0) + { + if (strcmp(te->desc, "AGGREGATE") == 0 || + strcmp(te->desc, "BLOB") == 0 || + strcmp(te->desc, "COLLATION") == 0 || + strcmp(te->desc, "CONVERSION") == 0 || + strcmp(te->desc, "DATABASE") == 0 || + strcmp(te->desc, "DOMAIN") == 0 || + strcmp(te->desc, "FUNCTION") == 0 || + strcmp(te->desc, "OPERATOR") == 0 || + strcmp(te->desc, "OPERATOR CLASS") == 0 || + strcmp(te->desc, "OPERATOR FAMILY") == 0 || + strcmp(te->desc, "PROCEDURE") == 0 || + strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 || + strcmp(te->desc, "SCHEMA") == 0 || + strcmp(te->desc, "EVENT TRIGGER") == 0 || + strcmp(te->desc, "TABLE") == 0 || + strcmp(te->desc, "TYPE") == 0 || + strcmp(te->desc, "VIEW") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW") == 0 || + strcmp(te->desc, "SEQUENCE") == 0 || + strcmp(te->desc, "FOREIGN TABLE") == 0 || + strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 || + strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 || + strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 || + strcmp(te->desc, "SERVER") == 0 || + strcmp(te->desc, "STATISTICS") == 0 || + strcmp(te->desc, "PUBLICATION") == 0 || + strcmp(te->desc, "SUBSCRIPTION") == 0) + { + PQExpBuffer temp = createPQExpBuffer(); + + appendPQExpBufferStr(temp, "ALTER "); + _getObjectDescription(temp, te); + appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner)); + ahprintf(AH, "%s\n\n", temp->data); + destroyPQExpBuffer(temp); + } + else if (strcmp(te->desc, "CAST") == 0 || + strcmp(te->desc, "CHECK CONSTRAINT") == 0 || + strcmp(te->desc, "CONSTRAINT") == 0 || + strcmp(te->desc, "DATABASE PROPERTIES") == 0 || + strcmp(te->desc, "DEFAULT") == 0 || + strcmp(te->desc, "FK CONSTRAINT") == 0 || + strcmp(te->desc, "INDEX") == 0 || + strcmp(te->desc, "RULE") == 0 || + strcmp(te->desc, "TRIGGER") == 0 || + strcmp(te->desc, "ROW SECURITY") == 0 || + strcmp(te->desc, "POLICY") == 0 || + strcmp(te->desc, "USER MAPPING") == 0) + { + /* these object types don't have separate owners */ + } + else + { + pg_log_warning("don't know how to set owner for object type \"%s\"", + te->desc); + } + } + + /* + * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION + * commands, so we can no longer assume we know the current auth setting. + */ + if (_tocEntryIsACL(te)) + { + if (AH->currUser) + free(AH->currUser); + AH->currUser = NULL; + } +} + +/* + * Sanitize a string to be included in an SQL comment or TOC listing, by + * replacing any newlines with spaces. This ensures each logical output line + * is in fact one physical output line, to prevent corruption of the dump + * (which could, in the worst case, present an SQL injection vulnerability + * if someone were to incautiously load a dump containing objects with + * maliciously crafted names). + * + * The result is a freshly malloc'd string. If the input string is NULL, + * return a malloc'ed empty string, unless want_hyphen, in which case return a + * malloc'ed hyphen. + * + * Note that we currently don't bother to quote names, meaning that the name + * fields aren't automatically parseable. "pg_restore -L" doesn't care because + * it only examines the dumpId field, but someday we might want to try harder. + */ +static char * +sanitize_line(const char *str, bool want_hyphen) +{ + char *result; + char *s; + + if (!str) + return pg_strdup(want_hyphen ? "-" : ""); + + result = pg_strdup(str); + + for (s = result; *s != '\0'; s++) + { + if (*s == '\n' || *s == '\r') + *s = ' '; + } + + return result; +} + +/* + * Write the file header for a custom-format archive + */ +void +WriteHead(ArchiveHandle *AH) +{ + struct tm crtm; + + AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */ + AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version)); + AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version)); + AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version)); + AH->WriteBytePtr(AH, AH->intSize); + AH->WriteBytePtr(AH, AH->offSize); + AH->WriteBytePtr(AH, AH->format); + WriteInt(AH, AH->compression); + crtm = *localtime(&AH->createDate); + WriteInt(AH, crtm.tm_sec); + WriteInt(AH, crtm.tm_min); + WriteInt(AH, crtm.tm_hour); + WriteInt(AH, crtm.tm_mday); + WriteInt(AH, crtm.tm_mon); + WriteInt(AH, crtm.tm_year); + WriteInt(AH, crtm.tm_isdst); + WriteStr(AH, PQdb(AH->connection)); + WriteStr(AH, AH->public.remoteVersionStr); + WriteStr(AH, PG_VERSION); +} + +void +ReadHead(ArchiveHandle *AH) +{ + char vmaj, + vmin, + vrev; + int fmt; + + /* + * If we haven't already read the header, do so. + * + * NB: this code must agree with _discoverArchiveFormat(). Maybe find a + * way to unify the cases? + */ + if (!AH->readHeader) + { + char tmpMag[7]; + + AH->ReadBufPtr(AH, tmpMag, 5); + + if (strncmp(tmpMag, "PGDMP", 5) != 0) + fatal("did not find magic string in file header"); + } + + vmaj = AH->ReadBytePtr(AH); + vmin = AH->ReadBytePtr(AH); + + if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */ + vrev = AH->ReadBytePtr(AH); + else + vrev = 0; + + AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev); + + if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX) + fatal("unsupported version (%d.%d) in file header", + vmaj, vmin); + + AH->intSize = AH->ReadBytePtr(AH); + if (AH->intSize > 32) + fatal("sanity check on integer size (%lu) failed", + (unsigned long) AH->intSize); + + if (AH->intSize > sizeof(int)) + pg_log_warning("archive was made on a machine with larger integers, some operations might fail"); + + if (AH->version >= K_VERS_1_7) + AH->offSize = AH->ReadBytePtr(AH); + else + AH->offSize = AH->intSize; + + fmt = AH->ReadBytePtr(AH); + + if (AH->format != fmt) + fatal("expected format (%d) differs from format found in file (%d)", + AH->format, fmt); + + if (AH->version >= K_VERS_1_2) + { + if (AH->version < K_VERS_1_4) + AH->compression = AH->ReadBytePtr(AH); + else + AH->compression = ReadInt(AH); + } + else + AH->compression = Z_DEFAULT_COMPRESSION; + +#ifndef HAVE_LIBZ + if (AH->compression != 0) + pg_log_warning("archive is compressed, but this installation does not support compression -- no data will be available"); +#endif + + if (AH->version >= K_VERS_1_4) + { + struct tm crtm; + + crtm.tm_sec = ReadInt(AH); + crtm.tm_min = ReadInt(AH); + crtm.tm_hour = ReadInt(AH); + crtm.tm_mday = ReadInt(AH); + crtm.tm_mon = ReadInt(AH); + crtm.tm_year = ReadInt(AH); + crtm.tm_isdst = ReadInt(AH); + + /* + * Newer versions of glibc have mktime() report failure if tm_isdst is + * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when + * TZ=UTC. This is problematic when restoring an archive under a + * different timezone setting. If we get a failure, try again with + * tm_isdst set to -1 ("don't know"). + * + * XXX with or without this hack, we reconstruct createDate + * incorrectly when the prevailing timezone is different from + * pg_dump's. Next time we bump the archive version, we should flush + * this representation and store a plain seconds-since-the-Epoch + * timestamp instead. + */ + AH->createDate = mktime(&crtm); + if (AH->createDate == (time_t) -1) + { + crtm.tm_isdst = -1; + AH->createDate = mktime(&crtm); + if (AH->createDate == (time_t) -1) + pg_log_warning("invalid creation date in header"); + } + } + + if (AH->version >= K_VERS_1_4) + { + AH->archdbname = ReadStr(AH); + } + + if (AH->version >= K_VERS_1_10) + { + AH->archiveRemoteVersion = ReadStr(AH); + AH->archiveDumpVersion = ReadStr(AH); + } +} + + +/* + * checkSeek + * check to see if ftell/fseek can be performed. + */ +bool +checkSeek(FILE *fp) +{ + pgoff_t tpos; + + /* Check that ftello works on this file */ + tpos = ftello(fp); + if (tpos < 0) + return false; + + /* + * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test + * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a + * successful no-op even on files that are otherwise unseekable. + */ + if (fseeko(fp, tpos, SEEK_SET) != 0) + return false; + + return true; +} + + +/* + * dumpTimestamp + */ +static void +dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim) +{ + char buf[64]; + + if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0) + ahprintf(AH, "-- %s %s\n\n", msg, buf); +} + +/* + * Main engine for parallel restore. + * + * Parallel restore is done in three phases. In this first phase, + * we'll process all SECTION_PRE_DATA TOC entries that are allowed to be + * processed in the RESTORE_PASS_MAIN pass. (In practice, that's all + * PRE_DATA items other than ACLs.) Entries we can't process now are + * added to the pending_list for later phases to deal with. + */ +static void +restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list) +{ + bool skipped_some; + TocEntry *next_work_item; + + pg_log_debug("entering restore_toc_entries_prefork"); + + /* Adjust dependency information */ + fix_dependencies(AH); + + /* + * Do all the early stuff in a single connection in the parent. There's no + * great point in running it in parallel, in fact it will actually run + * faster in a single connection because we avoid all the connection and + * setup overhead. Also, pre-9.2 pg_dump versions were not very good + * about showing all the dependencies of SECTION_PRE_DATA items, so we do + * not risk trying to process them out-of-order. + * + * Stuff that we can't do immediately gets added to the pending_list. + * Note: we don't yet filter out entries that aren't going to be restored. + * They might participate in dependency chains connecting entries that + * should be restored, so we treat them as live until we actually process + * them. + * + * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear + * before DATA items, and all DATA items before POST_DATA items. That is + * not certain to be true in older archives, though, and in any case use + * of a list file would destroy that ordering (cf. SortTocFromFile). So + * this loop cannot assume that it holds. + */ + AH->restorePass = RESTORE_PASS_MAIN; + skipped_some = false; + for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next) + { + bool do_now = true; + + if (next_work_item->section != SECTION_PRE_DATA) + { + /* DATA and POST_DATA items are just ignored for now */ + if (next_work_item->section == SECTION_DATA || + next_work_item->section == SECTION_POST_DATA) + { + do_now = false; + skipped_some = true; + } + else + { + /* + * SECTION_NONE items, such as comments, can be processed now + * if we are still in the PRE_DATA part of the archive. Once + * we've skipped any items, we have to consider whether the + * comment's dependencies are satisfied, so skip it for now. + */ + if (skipped_some) + do_now = false; + } + } + + /* + * Also skip items that need to be forced into later passes. We need + * not set skipped_some in this case, since by assumption no main-pass + * items could depend on these. + */ + if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN) + do_now = false; + + if (do_now) + { + /* OK, restore the item and update its dependencies */ + pg_log_info("processing item %d %s %s", + next_work_item->dumpId, + next_work_item->desc, next_work_item->tag); + + (void) restore_toc_entry(AH, next_work_item, false); + + /* Reduce dependencies, but don't move anything to ready_list */ + reduce_dependencies(AH, next_work_item, NULL); + } + else + { + /* Nope, so add it to pending_list */ + pending_list_append(pending_list, next_work_item); + } + } + + /* + * Now close parent connection in prep for parallel steps. We do this + * mainly to ensure that we don't exceed the specified number of parallel + * connections. + */ + DisconnectDatabase(&AH->public); + + /* blow away any transient state from the old connection */ + if (AH->currUser) + free(AH->currUser); + AH->currUser = NULL; + if (AH->currSchema) + free(AH->currSchema); + AH->currSchema = NULL; + if (AH->currTablespace) + free(AH->currTablespace); + AH->currTablespace = NULL; + if (AH->currTableAm) + free(AH->currTableAm); + AH->currTableAm = NULL; +} + +/* + * Main engine for parallel restore. + * + * Parallel restore is done in three phases. In this second phase, + * we process entries by dispatching them to parallel worker children + * (processes on Unix, threads on Windows), each of which connects + * separately to the database. Inter-entry dependencies are respected, + * and so is the RestorePass multi-pass structure. When we can no longer + * make any entries ready to process, we exit. Normally, there will be + * nothing left to do; but if there is, the third phase will mop up. + */ +static void +restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, + TocEntry *pending_list) +{ + ParallelReadyList ready_list; + TocEntry *next_work_item; + + pg_log_debug("entering restore_toc_entries_parallel"); + + /* Set up ready_list with enough room for all known TocEntrys */ + ready_list_init(&ready_list, AH->tocCount); + + /* + * The pending_list contains all items that we need to restore. Move all + * items that are available to process immediately into the ready_list. + * After this setup, the pending list is everything that needs to be done + * but is blocked by one or more dependencies, while the ready list + * contains items that have no remaining dependencies and are OK to + * process in the current restore pass. + */ + AH->restorePass = RESTORE_PASS_MAIN; + move_to_ready_list(pending_list, &ready_list, AH->restorePass); + + /* + * main parent loop + * + * Keep going until there is no worker still running AND there is no work + * left to be done. Note invariant: at top of loop, there should always + * be at least one worker available to dispatch a job to. + */ + pg_log_info("entering main parallel loop"); + + for (;;) + { + /* Look for an item ready to be dispatched to a worker */ + next_work_item = pop_next_work_item(&ready_list, pstate); + if (next_work_item != NULL) + { + /* If not to be restored, don't waste time launching a worker */ + if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0) + { + pg_log_info("skipping item %d %s %s", + next_work_item->dumpId, + next_work_item->desc, next_work_item->tag); + /* Update its dependencies as though we'd completed it */ + reduce_dependencies(AH, next_work_item, &ready_list); + /* Loop around to see if anything else can be dispatched */ + continue; + } + + pg_log_info("launching item %d %s %s", + next_work_item->dumpId, + next_work_item->desc, next_work_item->tag); + + /* Dispatch to some worker */ + DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE, + mark_restore_job_done, &ready_list); + } + else if (IsEveryWorkerIdle(pstate)) + { + /* + * Nothing is ready and no worker is running, so we're done with + * the current pass or maybe with the whole process. + */ + if (AH->restorePass == RESTORE_PASS_LAST) + break; /* No more parallel processing is possible */ + + /* Advance to next restore pass */ + AH->restorePass++; + /* That probably allows some stuff to be made ready */ + move_to_ready_list(pending_list, &ready_list, AH->restorePass); + /* Loop around to see if anything's now ready */ + continue; + } + else + { + /* + * We have nothing ready, but at least one child is working, so + * wait for some subjob to finish. + */ + } + + /* + * Before dispatching another job, check to see if anything has + * finished. We should check every time through the loop so as to + * reduce dependencies as soon as possible. If we were unable to + * dispatch any job this time through, wait until some worker finishes + * (and, hopefully, unblocks some pending item). If we did dispatch + * something, continue as soon as there's at least one idle worker. + * Note that in either case, there's guaranteed to be at least one + * idle worker when we return to the top of the loop. This ensures we + * won't block inside DispatchJobForTocEntry, which would be + * undesirable: we'd rather postpone dispatching until we see what's + * been unblocked by finished jobs. + */ + WaitForWorkers(AH, pstate, + next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS); + } + + /* There should now be nothing in ready_list. */ + Assert(ready_list.first_te > ready_list.last_te); + + ready_list_free(&ready_list); + + pg_log_info("finished main parallel loop"); +} + +/* + * Main engine for parallel restore. + * + * Parallel restore is done in three phases. In this third phase, + * we mop up any remaining TOC entries by processing them serially. + * This phase normally should have nothing to do, but if we've somehow + * gotten stuck due to circular dependencies or some such, this provides + * at least some chance of completing the restore successfully. + */ +static void +restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list) +{ + RestoreOptions *ropt = AH->public.ropt; + TocEntry *te; + + pg_log_debug("entering restore_toc_entries_postfork"); + + /* + * Now reconnect the single parent connection. + */ + ConnectDatabase((Archive *) AH, &ropt->cparams, true); + + /* re-establish fixed state */ + _doSetFixedOutputState(AH); + + /* + * Make sure there is no work left due to, say, circular dependencies, or + * some other pathological condition. If so, do it in the single parent + * connection. We don't sweat about RestorePass ordering; it's likely we + * already violated that. + */ + for (te = pending_list->pending_next; te != pending_list; te = te->pending_next) + { + pg_log_info("processing missed item %d %s %s", + te->dumpId, te->desc, te->tag); + (void) restore_toc_entry(AH, te, false); + } +} + +/* + * Check if te1 has an exclusive lock requirement for an item that te2 also + * requires, whether or not te2's requirement is for an exclusive lock. + */ +static bool +has_lock_conflicts(TocEntry *te1, TocEntry *te2) +{ + int j, + k; + + for (j = 0; j < te1->nLockDeps; j++) + { + for (k = 0; k < te2->nDeps; k++) + { + if (te1->lockDeps[j] == te2->dependencies[k]) + return true; + } + } + return false; +} + + +/* + * Initialize the header of the pending-items list. + * + * This is a circular list with a dummy TocEntry as header, just like the + * main TOC list; but we use separate list links so that an entry can be in + * the main TOC list as well as in the pending list. + */ +static void +pending_list_header_init(TocEntry *l) +{ + l->pending_prev = l->pending_next = l; +} + +/* Append te to the end of the pending-list headed by l */ +static void +pending_list_append(TocEntry *l, TocEntry *te) +{ + te->pending_prev = l->pending_prev; + l->pending_prev->pending_next = te; + l->pending_prev = te; + te->pending_next = l; +} + +/* Remove te from the pending-list */ +static void +pending_list_remove(TocEntry *te) +{ + te->pending_prev->pending_next = te->pending_next; + te->pending_next->pending_prev = te->pending_prev; + te->pending_prev = NULL; + te->pending_next = NULL; +} + + +/* + * Initialize the ready_list with enough room for up to tocCount entries. + */ +static void +ready_list_init(ParallelReadyList *ready_list, int tocCount) +{ + ready_list->tes = (TocEntry **) + pg_malloc(tocCount * sizeof(TocEntry *)); + ready_list->first_te = 0; + ready_list->last_te = -1; + ready_list->sorted = false; +} + +/* + * Free storage for a ready_list. + */ +static void +ready_list_free(ParallelReadyList *ready_list) +{ + pg_free(ready_list->tes); +} + +/* Add te to the ready_list */ +static void +ready_list_insert(ParallelReadyList *ready_list, TocEntry *te) +{ + ready_list->tes[++ready_list->last_te] = te; + /* List is (probably) not sorted anymore. */ + ready_list->sorted = false; +} + +/* Remove the i'th entry in the ready_list */ +static void +ready_list_remove(ParallelReadyList *ready_list, int i) +{ + int f = ready_list->first_te; + + Assert(i >= f && i <= ready_list->last_te); + + /* + * In the typical case where the item to be removed is the first ready + * entry, we need only increment first_te to remove it. Otherwise, move + * the entries before it to compact the list. (This preserves sortedness, + * if any.) We could alternatively move the entries after i, but there + * are typically many more of those. + */ + if (i > f) + { + TocEntry **first_te_ptr = &ready_list->tes[f]; + + memmove(first_te_ptr + 1, first_te_ptr, (i - f) * sizeof(TocEntry *)); + } + ready_list->first_te++; +} + +/* Sort the ready_list into the desired order */ +static void +ready_list_sort(ParallelReadyList *ready_list) +{ + if (!ready_list->sorted) + { + int n = ready_list->last_te - ready_list->first_te + 1; + + if (n > 1) + qsort(ready_list->tes + ready_list->first_te, n, + sizeof(TocEntry *), + TocEntrySizeCompare); + ready_list->sorted = true; + } +} + +/* qsort comparator for sorting TocEntries by dataLength */ +static int +TocEntrySizeCompare(const void *p1, const void *p2) +{ + const TocEntry *te1 = *(const TocEntry *const *) p1; + const TocEntry *te2 = *(const TocEntry *const *) p2; + + /* Sort by decreasing dataLength */ + if (te1->dataLength > te2->dataLength) + return -1; + if (te1->dataLength < te2->dataLength) + return 1; + + /* For equal dataLengths, sort by dumpId, just to be stable */ + if (te1->dumpId < te2->dumpId) + return -1; + if (te1->dumpId > te2->dumpId) + return 1; + + return 0; +} + + +/* + * Move all immediately-ready items from pending_list to ready_list. + * + * Items are considered ready if they have no remaining dependencies and + * they belong in the current restore pass. (See also reduce_dependencies, + * which applies the same logic one-at-a-time.) + */ +static void +move_to_ready_list(TocEntry *pending_list, + ParallelReadyList *ready_list, + RestorePass pass) +{ + TocEntry *te; + TocEntry *next_te; + + for (te = pending_list->pending_next; te != pending_list; te = next_te) + { + /* must save list link before possibly removing te from list */ + next_te = te->pending_next; + + if (te->depCount == 0 && + _tocEntryRestorePass(te) == pass) + { + /* Remove it from pending_list ... */ + pending_list_remove(te); + /* ... and add to ready_list */ + ready_list_insert(ready_list, te); + } + } +} + +/* + * Find the next work item (if any) that is capable of being run now, + * and remove it from the ready_list. + * + * Returns the item, or NULL if nothing is runnable. + * + * To qualify, the item must have no remaining dependencies + * and no requirements for locks that are incompatible with + * items currently running. Items in the ready_list are known to have + * no remaining dependencies, but we have to check for lock conflicts. + */ +static TocEntry * +pop_next_work_item(ParallelReadyList *ready_list, + ParallelState *pstate) +{ + /* + * Sort the ready_list so that we'll tackle larger jobs first. + */ + ready_list_sort(ready_list); + + /* + * Search the ready_list until we find a suitable item. + */ + for (int i = ready_list->first_te; i <= ready_list->last_te; i++) + { + TocEntry *te = ready_list->tes[i]; + bool conflicts = false; + + /* + * Check to see if the item would need exclusive lock on something + * that a currently running item also needs lock on, or vice versa. If + * so, we don't want to schedule them together. + */ + for (int k = 0; k < pstate->numWorkers; k++) + { + TocEntry *running_te = pstate->te[k]; + + if (running_te == NULL) + continue; + if (has_lock_conflicts(te, running_te) || + has_lock_conflicts(running_te, te)) + { + conflicts = true; + break; + } + } + + if (conflicts) + continue; + + /* passed all tests, so this item can run */ + ready_list_remove(ready_list, i); + return te; + } + + pg_log_debug("no item ready"); + return NULL; +} + + +/* + * Restore a single TOC item in parallel with others + * + * this is run in the worker, i.e. in a thread (Windows) or a separate process + * (everything else). A worker process executes several such work items during + * a parallel backup or restore. Once we terminate here and report back that + * our work is finished, the leader process will assign us a new work item. + */ +int +parallel_restore(ArchiveHandle *AH, TocEntry *te) +{ + int status; + + Assert(AH->connection != NULL); + + /* Count only errors associated with this TOC entry */ + AH->public.n_errors = 0; + + /* Restore the TOC item */ + status = restore_toc_entry(AH, te, true); + + return status; +} + + +/* + * Callback function that's invoked in the leader process after a step has + * been parallel restored. + * + * Update status and reduce the dependency count of any dependent items. + */ +static void +mark_restore_job_done(ArchiveHandle *AH, + TocEntry *te, + int status, + void *callback_data) +{ + ParallelReadyList *ready_list = (ParallelReadyList *) callback_data; + + pg_log_info("finished item %d %s %s", + te->dumpId, te->desc, te->tag); + + if (status == WORKER_CREATE_DONE) + mark_create_done(AH, te); + else if (status == WORKER_INHIBIT_DATA) + { + inhibit_data_for_failed_table(AH, te); + AH->public.n_errors++; + } + else if (status == WORKER_IGNORED_ERRORS) + AH->public.n_errors++; + else if (status != 0) + fatal("worker process failed: exit code %d", + status); + + reduce_dependencies(AH, te, ready_list); +} + + +/* + * Process the dependency information into a form useful for parallel restore. + * + * This function takes care of fixing up some missing or badly designed + * dependencies, and then prepares subsidiary data structures that will be + * used in the main parallel-restore logic, including: + * 1. We build the revDeps[] arrays of incoming dependency dumpIds. + * 2. We set up depCount fields that are the number of as-yet-unprocessed + * dependencies for each TOC entry. + * + * We also identify locking dependencies so that we can avoid trying to + * schedule conflicting items at the same time. + */ +static void +fix_dependencies(ArchiveHandle *AH) +{ + TocEntry *te; + int i; + + /* + * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC + * items are marked as not being in any parallel-processing list. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + te->depCount = te->nDeps; + te->revDeps = NULL; + te->nRevDeps = 0; + te->pending_prev = NULL; + te->pending_next = NULL; + } + + /* + * POST_DATA items that are shown as depending on a table need to be + * re-pointed to depend on that table's data, instead. This ensures they + * won't get scheduled until the data has been loaded. + */ + repoint_table_dependencies(AH); + + /* + * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB + * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only + * one BLOB COMMENTS in such files.) + */ + if (AH->version < K_VERS_1_11) + { + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0) + { + TocEntry *te2; + + for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next) + { + if (strcmp(te2->desc, "BLOBS") == 0) + { + te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId)); + te->dependencies[0] = te2->dumpId; + te->nDeps++; + te->depCount++; + break; + } + } + break; + } + } + } + + /* + * At this point we start to build the revDeps reverse-dependency arrays, + * so all changes of dependencies must be complete. + */ + + /* + * Count the incoming dependencies for each item. Also, it is possible + * that the dependencies list items that are not in the archive at all + * (that should not happen in 9.2 and later, but is highly likely in older + * archives). Subtract such items from the depCounts. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + for (i = 0; i < te->nDeps; i++) + { + DumpId depid = te->dependencies[i]; + + if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL) + AH->tocsByDumpId[depid]->nRevDeps++; + else + te->depCount--; + } + } + + /* + * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use + * it as a counter below. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (te->nRevDeps > 0) + te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId)); + te->nRevDeps = 0; + } + + /* + * Build the revDeps[] arrays of incoming-dependency dumpIds. This had + * better agree with the loops above. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + for (i = 0; i < te->nDeps; i++) + { + DumpId depid = te->dependencies[i]; + + if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL) + { + TocEntry *otherte = AH->tocsByDumpId[depid]; + + otherte->revDeps[otherte->nRevDeps++] = te->dumpId; + } + } + } + + /* + * Lastly, work out the locking dependencies. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + te->lockDeps = NULL; + te->nLockDeps = 0; + identify_locking_dependencies(AH, te); + } +} + +/* + * Change dependencies on table items to depend on table data items instead, + * but only in POST_DATA items. + * + * Also, for any item having such dependency(s), set its dataLength to the + * largest dataLength of the table data items it depends on. This ensures + * that parallel restore will prioritize larger jobs (index builds, FK + * constraint checks, etc) over smaller ones, avoiding situations where we + * end a restore with only one active job working on a large table. + */ +static void +repoint_table_dependencies(ArchiveHandle *AH) +{ + TocEntry *te; + int i; + DumpId olddep; + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (te->section != SECTION_POST_DATA) + continue; + for (i = 0; i < te->nDeps; i++) + { + olddep = te->dependencies[i]; + if (olddep <= AH->maxDumpId && + AH->tableDataId[olddep] != 0) + { + DumpId tabledataid = AH->tableDataId[olddep]; + TocEntry *tabledatate = AH->tocsByDumpId[tabledataid]; + + te->dependencies[i] = tabledataid; + te->dataLength = Max(te->dataLength, tabledatate->dataLength); + pg_log_debug("transferring dependency %d -> %d to %d", + te->dumpId, olddep, tabledataid); + } + } + } +} + +/* + * Identify which objects we'll need exclusive lock on in order to restore + * the given TOC entry (*other* than the one identified by the TOC entry + * itself). Record their dump IDs in the entry's lockDeps[] array. + */ +static void +identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te) +{ + DumpId *lockids; + int nlockids; + int i; + + /* + * We only care about this for POST_DATA items. PRE_DATA items are not + * run in parallel, and DATA items are all independent by assumption. + */ + if (te->section != SECTION_POST_DATA) + return; + + /* Quick exit if no dependencies at all */ + if (te->nDeps == 0) + return; + + /* + * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that, + * and hence require exclusive lock. However, we know that CREATE INDEX + * does not. (Maybe someday index-creating CONSTRAINTs will fall in that + * category too ... but today is not that day.) + */ + if (strcmp(te->desc, "INDEX") == 0) + return; + + /* + * We assume the entry requires exclusive lock on each TABLE or TABLE DATA + * item listed among its dependencies. Originally all of these would have + * been TABLE items, but repoint_table_dependencies would have repointed + * them to the TABLE DATA items if those are present (which they might not + * be, eg in a schema-only dump). Note that all of the entries we are + * processing here are POST_DATA; otherwise there might be a significant + * difference between a dependency on a table and a dependency on its + * data, so that closer analysis would be needed here. + */ + lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId)); + nlockids = 0; + for (i = 0; i < te->nDeps; i++) + { + DumpId depid = te->dependencies[i]; + + if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL && + ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) || + strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0)) + lockids[nlockids++] = depid; + } + + if (nlockids == 0) + { + free(lockids); + return; + } + + te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId)); + te->nLockDeps = nlockids; +} + +/* + * Remove the specified TOC entry from the depCounts of items that depend on + * it, thereby possibly making them ready-to-run. Any pending item that + * becomes ready should be moved to the ready_list, if that's provided. + */ +static void +reduce_dependencies(ArchiveHandle *AH, TocEntry *te, + ParallelReadyList *ready_list) +{ + int i; + + pg_log_debug("reducing dependencies for %d", te->dumpId); + + for (i = 0; i < te->nRevDeps; i++) + { + TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]]; + + Assert(otherte->depCount > 0); + otherte->depCount--; + + /* + * It's ready if it has no remaining dependencies, and it belongs in + * the current restore pass, and it is currently a member of the + * pending list (that check is needed to prevent double restore in + * some cases where a list-file forces out-of-order restoring). + * However, if ready_list == NULL then caller doesn't want any list + * memberships changed. + */ + if (otherte->depCount == 0 && + _tocEntryRestorePass(otherte) == AH->restorePass && + otherte->pending_prev != NULL && + ready_list != NULL) + { + /* Remove it from pending list ... */ + pending_list_remove(otherte); + /* ... and add to ready_list */ + ready_list_insert(ready_list, otherte); + } + } +} + +/* + * Set the created flag on the DATA member corresponding to the given + * TABLE member + */ +static void +mark_create_done(ArchiveHandle *AH, TocEntry *te) +{ + if (AH->tableDataId[te->dumpId] != 0) + { + TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]]; + + ted->created = true; + } +} + +/* + * Mark the DATA member corresponding to the given TABLE member + * as not wanted + */ +static void +inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te) +{ + pg_log_info("table \"%s\" could not be created, will not restore its data", + te->tag); + + if (AH->tableDataId[te->dumpId] != 0) + { + TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]]; + + ted->reqs = 0; + } +} + +/* + * Clone and de-clone routines used in parallel restoration. + * + * Enough of the structure is cloned to ensure that there is no + * conflict between different threads each with their own clone. + */ +ArchiveHandle * +CloneArchive(ArchiveHandle *AH) +{ + ArchiveHandle *clone; + + /* Make a "flat" copy */ + clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle)); + memcpy(clone, AH, sizeof(ArchiveHandle)); + + /* Handle format-independent fields */ + memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse)); + + /* The clone will have its own connection, so disregard connection state */ + clone->connection = NULL; + clone->connCancel = NULL; + clone->currUser = NULL; + clone->currSchema = NULL; + clone->currTablespace = NULL; + + /* savedPassword must be local in case we change it while connecting */ + if (clone->savedPassword) + clone->savedPassword = pg_strdup(clone->savedPassword); + + /* clone has its own error count, too */ + clone->public.n_errors = 0; + + /* + * Connect our new clone object to the database, using the same connection + * parameters used for the original connection. + */ + ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true); + + /* re-establish fixed state */ + if (AH->mode == archModeRead) + _doSetFixedOutputState(clone); + /* in write case, setupDumpWorker will fix up connection state */ + + /* Let the format-specific code have a chance too */ + clone->ClonePtr(clone); + + Assert(clone->connection != NULL); + return clone; +} + +/* + * Release clone-local storage. + * + * Note: we assume any clone-local connection was already closed. + */ +void +DeCloneArchive(ArchiveHandle *AH) +{ + /* Should not have an open database connection */ + Assert(AH->connection == NULL); + + /* Clear format-specific state */ + AH->DeClonePtr(AH); + + /* Clear state allocated by CloneArchive */ + if (AH->sqlparse.curCmd) + destroyPQExpBuffer(AH->sqlparse.curCmd); + + /* Clear any connection-local state */ + if (AH->currUser) + free(AH->currUser); + if (AH->currSchema) + free(AH->currSchema); + if (AH->currTablespace) + free(AH->currTablespace); + if (AH->currTableAm) + free(AH->currTableAm); + if (AH->savedPassword) + free(AH->savedPassword); + + free(AH); +} diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h new file mode 100644 index 0000000..9106094 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -0,0 +1,487 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_archiver.h + * + * Private interface to the pg_dump archiver routines. + * It is NOT intended that these routines be called by any + * dumper directly. + * + * See the headers to pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_archiver.h + * + *------------------------------------------------------------------------- + */ +#ifndef __PG_BACKUP_ARCHIVE__ +#define __PG_BACKUP_ARCHIVE__ + +#include + +#include "libpq-fe.h" +#include "pg_backup.h" +#include "pqexpbuffer.h" + +#define LOBBUFSIZE 16384 + +/* + * Note: zlib.h must be included *after* libpq-fe.h, because the latter may + * include ssl.h, which has a naming conflict with zlib.h. + */ +#ifdef HAVE_LIBZ +#include +#define GZCLOSE(fh) gzclose(fh) +#define GZWRITE(p, s, n, fh) gzwrite(fh, p, (n) * (s)) +#define GZREAD(p, s, n, fh) gzread(fh, p, (n) * (s)) +#define GZEOF(fh) gzeof(fh) +#else +#define GZCLOSE(fh) fclose(fh) +#define GZWRITE(p, s, n, fh) (fwrite(p, s, n, fh) * (s)) +#define GZREAD(p, s, n, fh) fread(p, s, n, fh) +#define GZEOF(fh) feof(fh) +/* this is just the redefinition of a libz constant */ +#define Z_DEFAULT_COMPRESSION (-1) + +typedef struct _z_stream +{ + void *next_in; + void *next_out; + size_t avail_in; + size_t avail_out; +} z_stream; +typedef z_stream *z_streamp; +#endif + +/* Data block types */ +#define BLK_DATA 1 +#define BLK_BLOBS 3 + +/* Encode version components into a convenient integer */ +#define MAKE_ARCHIVE_VERSION(major, minor, rev) (((major) * 256 + (minor)) * 256 + (rev)) + +#define ARCHIVE_MAJOR(version) (((version) >> 16) & 255) +#define ARCHIVE_MINOR(version) (((version) >> 8) & 255) +#define ARCHIVE_REV(version) (((version) ) & 255) + +/* Historical version numbers (checked in code) */ +#define K_VERS_1_0 MAKE_ARCHIVE_VERSION(1, 0, 0) +#define K_VERS_1_2 MAKE_ARCHIVE_VERSION(1, 2, 0) /* Allow No ZLIB */ +#define K_VERS_1_3 MAKE_ARCHIVE_VERSION(1, 3, 0) /* BLOBs */ +#define K_VERS_1_4 MAKE_ARCHIVE_VERSION(1, 4, 0) /* Date & name in header */ +#define K_VERS_1_5 MAKE_ARCHIVE_VERSION(1, 5, 0) /* Handle dependencies */ +#define K_VERS_1_6 MAKE_ARCHIVE_VERSION(1, 6, 0) /* Schema field in TOCs */ +#define K_VERS_1_7 MAKE_ARCHIVE_VERSION(1, 7, 0) /* File Offset size in + * header */ +#define K_VERS_1_8 MAKE_ARCHIVE_VERSION(1, 8, 0) /* change interpretation + * of ID numbers and + * dependencies */ +#define K_VERS_1_9 MAKE_ARCHIVE_VERSION(1, 9, 0) /* add default_with_oids + * tracking */ +#define K_VERS_1_10 MAKE_ARCHIVE_VERSION(1, 10, 0) /* add tablespace */ +#define K_VERS_1_11 MAKE_ARCHIVE_VERSION(1, 11, 0) /* add toc section + * indicator */ +#define K_VERS_1_12 MAKE_ARCHIVE_VERSION(1, 12, 0) /* add separate BLOB + * entries */ +#define K_VERS_1_13 MAKE_ARCHIVE_VERSION(1, 13, 0) /* change search_path + * behavior */ +#define K_VERS_1_14 MAKE_ARCHIVE_VERSION(1, 14, 0) /* add tableam */ + +/* Current archive version number (the format we can output) */ +#define K_VERS_MAJOR 1 +#define K_VERS_MINOR 14 +#define K_VERS_REV 0 +#define K_VERS_SELF MAKE_ARCHIVE_VERSION(K_VERS_MAJOR, K_VERS_MINOR, K_VERS_REV) + +/* Newest format we can read */ +#define K_VERS_MAX MAKE_ARCHIVE_VERSION(K_VERS_MAJOR, K_VERS_MINOR, 255) + + +/* Flags to indicate disposition of offsets stored in files */ +#define K_OFFSET_POS_NOT_SET 1 +#define K_OFFSET_POS_SET 2 +#define K_OFFSET_NO_DATA 3 + +/* + * Special exit values from worker children. We reserve 0 for normal + * success; 1 and other small values should be interpreted as crashes. + */ +#define WORKER_OK 0 +#define WORKER_CREATE_DONE 10 +#define WORKER_INHIBIT_DATA 11 +#define WORKER_IGNORED_ERRORS 12 + +typedef struct _archiveHandle ArchiveHandle; +typedef struct _tocEntry TocEntry; +struct ParallelState; + +#define READ_ERROR_EXIT(fd) \ + do { \ + if (feof(fd)) \ + fatal("could not read from input file: end of file"); \ + else \ + fatal("could not read from input file: %m"); \ + } while (0) + +#define WRITE_ERROR_EXIT \ + do { \ + fatal("could not write to output file: %m"); \ + } while (0) + +typedef enum T_Action +{ + ACT_DUMP, + ACT_RESTORE +} T_Action; + +typedef void (*ClosePtrType) (ArchiveHandle *AH); +typedef void (*ReopenPtrType) (ArchiveHandle *AH); +typedef void (*ArchiveEntryPtrType) (ArchiveHandle *AH, TocEntry *te); + +typedef void (*StartDataPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef void (*WriteDataPtrType) (ArchiveHandle *AH, const void *data, size_t dLen); +typedef void (*EndDataPtrType) (ArchiveHandle *AH, TocEntry *te); + +typedef void (*StartBlobsPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef void (*StartBlobPtrType) (ArchiveHandle *AH, TocEntry *te, Oid oid); +typedef void (*EndBlobPtrType) (ArchiveHandle *AH, TocEntry *te, Oid oid); +typedef void (*EndBlobsPtrType) (ArchiveHandle *AH, TocEntry *te); + +typedef int (*WriteBytePtrType) (ArchiveHandle *AH, const int i); +typedef int (*ReadBytePtrType) (ArchiveHandle *AH); +typedef void (*WriteBufPtrType) (ArchiveHandle *AH, const void *c, size_t len); +typedef void (*ReadBufPtrType) (ArchiveHandle *AH, void *buf, size_t len); +typedef void (*WriteExtraTocPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef void (*ReadExtraTocPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef void (*PrintExtraTocPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef void (*PrintTocDataPtrType) (ArchiveHandle *AH, TocEntry *te); + +typedef void (*PrepParallelRestorePtrType) (ArchiveHandle *AH); +typedef void (*ClonePtrType) (ArchiveHandle *AH); +typedef void (*DeClonePtrType) (ArchiveHandle *AH); + +typedef int (*WorkerJobDumpPtrType) (ArchiveHandle *AH, TocEntry *te); +typedef int (*WorkerJobRestorePtrType) (ArchiveHandle *AH, TocEntry *te); + +typedef size_t (*CustomOutPtrType) (ArchiveHandle *AH, const void *buf, size_t len); + +typedef enum +{ + SQL_SCAN = 0, /* normal */ + SQL_IN_SINGLE_QUOTE, /* '...' literal */ + SQL_IN_DOUBLE_QUOTE /* "..." identifier */ +} sqlparseState; + +typedef struct +{ + sqlparseState state; /* see above */ + bool backSlash; /* next char is backslash quoted? */ + PQExpBuffer curCmd; /* incomplete line (NULL if not created) */ +} sqlparseInfo; + +typedef enum +{ + STAGE_NONE = 0, + STAGE_INITIALIZING, + STAGE_PROCESSING, + STAGE_FINALIZING +} ArchiverStage; + +typedef enum +{ + OUTPUT_SQLCMDS = 0, /* emitting general SQL commands */ + OUTPUT_COPYDATA, /* writing COPY data */ + OUTPUT_OTHERDATA /* writing data as INSERT commands */ +} ArchiverOutput; + +/* + * For historical reasons, ACL items are interspersed with everything else in + * a dump file's TOC; typically they're right after the object they're for. + * However, we need to restore data before ACLs, as otherwise a read-only + * table (ie one where the owner has revoked her own INSERT privilege) causes + * data restore failures. On the other hand, matview REFRESH commands should + * come out after ACLs, as otherwise non-superuser-owned matviews might not + * be able to execute. (If the permissions at the time of dumping would not + * allow a REFRESH, too bad; we won't fix that for you.) We also want event + * triggers to be restored after ACLs, so that they can't mess those up. + * + * These considerations force us to make three passes over the TOC, + * restoring the appropriate subset of items in each pass. We assume that + * the dependency sort resulted in an appropriate ordering of items within + * each subset. + * + * XXX This mechanism should be superseded by tracking dependencies on ACLs + * properly; but we'll still need it for old dump files even after that. + */ +typedef enum +{ + RESTORE_PASS_MAIN = 0, /* Main pass (most TOC item types) */ + RESTORE_PASS_ACL, /* ACL item types */ + RESTORE_PASS_POST_ACL /* Event trigger and matview refresh items */ + +#define RESTORE_PASS_LAST RESTORE_PASS_POST_ACL +} RestorePass; + +#define REQ_SCHEMA 0x01 /* want schema */ +#define REQ_DATA 0x02 /* want data */ +#define REQ_SPECIAL 0x04 /* for special TOC entries */ + +struct _archiveHandle +{ + Archive public; /* Public part of archive */ + int version; /* Version of file */ + + char *archiveRemoteVersion; /* When reading an archive, the + * version of the dumped DB */ + char *archiveDumpVersion; /* When reading an archive, the version of + * the dumper */ + + size_t intSize; /* Size of an integer in the archive */ + size_t offSize; /* Size of a file offset in the archive - + * Added V1.7 */ + ArchiveFormat format; /* Archive format */ + + sqlparseInfo sqlparse; /* state for parsing INSERT data */ + + time_t createDate; /* Date archive created */ + + /* + * Fields used when discovering archive format. For tar format, we load + * the first block into the lookahead buffer, and verify that it looks + * like a tar header. The tar module must then consume bytes from the + * lookahead buffer before reading any more from the file. For custom + * format, we load only the "PGDMP" marker into the buffer, and then set + * readHeader after confirming it matches. The buffer is vestigial in + * this case, as the subsequent code just checks readHeader and doesn't + * examine the buffer. + */ + int readHeader; /* Set if we already read "PGDMP" marker */ + char *lookahead; /* Buffer used when reading header to discover + * format */ + size_t lookaheadSize; /* Allocated size of buffer */ + size_t lookaheadLen; /* Length of valid data in lookahead */ + size_t lookaheadPos; /* Current read position in lookahead buffer */ + + ArchiveEntryPtrType ArchiveEntryPtr; /* Called for each metadata object */ + StartDataPtrType StartDataPtr; /* Called when table data is about to be + * dumped */ + WriteDataPtrType WriteDataPtr; /* Called to send some table data to the + * archive */ + EndDataPtrType EndDataPtr; /* Called when table data dump is finished */ + WriteBytePtrType WriteBytePtr; /* Write a byte to output */ + ReadBytePtrType ReadBytePtr; /* Read a byte from an archive */ + WriteBufPtrType WriteBufPtr; /* Write a buffer of output to the archive */ + ReadBufPtrType ReadBufPtr; /* Read a buffer of input from the archive */ + ClosePtrType ClosePtr; /* Close the archive */ + ReopenPtrType ReopenPtr; /* Reopen the archive */ + WriteExtraTocPtrType WriteExtraTocPtr; /* Write extra TOC entry data + * associated with the current + * archive format */ + ReadExtraTocPtrType ReadExtraTocPtr; /* Read extra info associated with + * archive format */ + PrintExtraTocPtrType PrintExtraTocPtr; /* Extra TOC info for format */ + PrintTocDataPtrType PrintTocDataPtr; + + StartBlobsPtrType StartBlobsPtr; + EndBlobsPtrType EndBlobsPtr; + StartBlobPtrType StartBlobPtr; + EndBlobPtrType EndBlobPtr; + + SetupWorkerPtrType SetupWorkerPtr; + WorkerJobDumpPtrType WorkerJobDumpPtr; + WorkerJobRestorePtrType WorkerJobRestorePtr; + + PrepParallelRestorePtrType PrepParallelRestorePtr; + ClonePtrType ClonePtr; /* Clone format-specific fields */ + DeClonePtrType DeClonePtr; /* Clean up cloned fields */ + + CustomOutPtrType CustomOutPtr; /* Alternative script output routine */ + + /* Stuff for direct DB connection */ + char *archdbname; /* DB name *read* from archive */ + char *savedPassword; /* password for ropt->username, if known */ + char *use_role; + PGconn *connection; + /* If connCancel isn't NULL, SIGINT handler will send a cancel */ + PGcancel *volatile connCancel; + + int connectToDB; /* Flag to indicate if direct DB connection is + * required */ + ArchiverOutput outputKind; /* Flag for what we're currently writing */ + bool pgCopyIn; /* Currently in libpq 'COPY IN' mode. */ + + int loFd; /* BLOB fd */ + int writingBlob; /* Flag */ + int blobCount; /* # of blobs restored */ + + char *fSpec; /* Archive File Spec */ + FILE *FH; /* General purpose file handle */ + void *OF; + int gzOut; /* Output file */ + + struct _tocEntry *toc; /* Header of circular list of TOC entries */ + int tocCount; /* Number of TOC entries */ + DumpId maxDumpId; /* largest DumpId among all TOC entries */ + + /* arrays created after the TOC list is complete: */ + struct _tocEntry **tocsByDumpId; /* TOCs indexed by dumpId */ + DumpId *tableDataId; /* TABLE DATA ids, indexed by table dumpId */ + + struct _tocEntry *currToc; /* Used when dumping data */ + int compression; /*--------- + * Compression requested on open(). + * Possible values for compression: + * -1 Z_DEFAULT_COMPRESSION + * 0 COMPRESSION_NONE + * 1-9 levels for gzip compression + *--------- + */ + bool dosync; /* data requested to be synced on sight */ + ArchiveMode mode; /* File mode - r or w */ + void *formatData; /* Header data specific to file format */ + + /* these vars track state to avoid sending redundant SET commands */ + char *currUser; /* current username, or NULL if unknown */ + char *currSchema; /* current schema, or NULL */ + char *currTablespace; /* current tablespace, or NULL */ + char *currTableAm; /* current table access method, or NULL */ + + void *lo_buf; + size_t lo_buf_used; + size_t lo_buf_size; + + int noTocComments; + ArchiverStage stage; + ArchiverStage lastErrorStage; + RestorePass restorePass; /* used only during parallel restore */ + struct _tocEntry *currentTE; + struct _tocEntry *lastErrorTE; +}; + +struct _tocEntry +{ + struct _tocEntry *prev; + struct _tocEntry *next; + CatalogId catalogId; + DumpId dumpId; + teSection section; + bool hadDumper; /* Archiver was passed a dumper routine (used + * in restore) */ + char *tag; /* index tag */ + char *namespace; /* null or empty string if not in a schema */ + char *tablespace; /* null if not in a tablespace; empty string + * means use database default */ + char *tableam; /* table access method, only for TABLE tags */ + char *owner; + char *desc; + char *defn; + char *dropStmt; + char *copyStmt; + DumpId *dependencies; /* dumpIds of objects this one depends on */ + int nDeps; /* number of dependencies */ + + DataDumperPtr dataDumper; /* Routine to dump data for object */ + const void *dataDumperArg; /* Arg for above routine */ + void *formatData; /* TOC Entry data specific to file format */ + + /* working state while dumping/restoring */ + pgoff_t dataLength; /* item's data size; 0 if none or unknown */ + int reqs; /* do we need schema and/or data of object + * (REQ_* bit mask) */ + bool created; /* set for DATA member if TABLE was created */ + + /* working state (needed only for parallel restore) */ + struct _tocEntry *pending_prev; /* list links for pending-items list; */ + struct _tocEntry *pending_next; /* NULL if not in that list */ + int depCount; /* number of dependencies not yet restored */ + DumpId *revDeps; /* dumpIds of objects depending on this one */ + int nRevDeps; /* number of such dependencies */ + DumpId *lockDeps; /* dumpIds of objects this one needs lock on */ + int nLockDeps; /* number of such dependencies */ +}; + +extern int parallel_restore(ArchiveHandle *AH, TocEntry *te); +extern void on_exit_close_archive(Archive *AHX); + +extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...) pg_attribute_printf(2, 3); + +/* Options for ArchiveEntry */ +typedef struct _archiveOpts +{ + const char *tag; + const char *namespace; + const char *tablespace; + const char *tableam; + const char *owner; + const char *description; + teSection section; + const char *createStmt; + const char *dropStmt; + const char *copyStmt; + const DumpId *deps; + int nDeps; + DataDumperPtr dumpFn; + const void *dumpArg; +} ArchiveOpts; +#define ARCHIVE_OPTS(...) &(ArchiveOpts){__VA_ARGS__} +/* Called to add a TOC entry */ +extern TocEntry *ArchiveEntry(Archive *AHX, CatalogId catalogId, + DumpId dumpId, ArchiveOpts *opts); + +extern void WriteHead(ArchiveHandle *AH); +extern void ReadHead(ArchiveHandle *AH); +extern void WriteToc(ArchiveHandle *AH); +extern void ReadToc(ArchiveHandle *AH); +extern void WriteDataChunks(ArchiveHandle *AH, struct ParallelState *pstate); +extern void WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te); +extern ArchiveHandle *CloneArchive(ArchiveHandle *AH); +extern void DeCloneArchive(ArchiveHandle *AH); + +extern int TocIDRequired(ArchiveHandle *AH, DumpId id); +TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id); +extern bool checkSeek(FILE *fp); + +#define appendStringLiteralAHX(buf,str,AH) \ + appendStringLiteral(buf, str, (AH)->public.encoding, (AH)->public.std_strings) + +#define appendByteaLiteralAHX(buf,str,len,AH) \ + appendByteaLiteral(buf, str, len, (AH)->public.std_strings) + +/* + * Mandatory routines for each supported format + */ + +extern size_t WriteInt(ArchiveHandle *AH, int i); +extern int ReadInt(ArchiveHandle *AH); +extern char *ReadStr(ArchiveHandle *AH); +extern size_t WriteStr(ArchiveHandle *AH, const char *s); + +int ReadOffset(ArchiveHandle *, pgoff_t *); +size_t WriteOffset(ArchiveHandle *, pgoff_t, int); + +extern void StartRestoreBlobs(ArchiveHandle *AH); +extern void StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop); +extern void EndRestoreBlob(ArchiveHandle *AH, Oid oid); +extern void EndRestoreBlobs(ArchiveHandle *AH); + +extern void InitArchiveFmt_Custom(ArchiveHandle *AH); +extern void InitArchiveFmt_Null(ArchiveHandle *AH); +extern void InitArchiveFmt_Directory(ArchiveHandle *AH); +extern void InitArchiveFmt_Tar(ArchiveHandle *AH); + +extern bool isValidTarHeader(char *header); + +extern void ReconnectToServer(ArchiveHandle *AH, const char *dbname); +extern void DropBlobIfExists(ArchiveHandle *AH, Oid oid); + +void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH); +int ahprintf(ArchiveHandle *AH, const char *fmt,...) pg_attribute_printf(2, 3); + +#endif diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c new file mode 100644 index 0000000..77d402c --- /dev/null +++ b/src/bin/pg_dump/pg_backup_custom.c @@ -0,0 +1,1022 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_custom.c + * + * Implements the custom output format. + * + * The comments with the routines in this code are a good place to + * understand how to write a new format. + * + * See the headers to pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * and any liability will be limited to the time taken to fix any + * related bug. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_custom.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "common/file_utils.h" +#include "compress_io.h" +#include "parallel.h" +#include "pg_backup_utils.h" + +/*-------- + * Routines in the format interface + *-------- + */ + +static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); +static void _StartData(ArchiveHandle *AH, TocEntry *te); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _EndData(ArchiveHandle *AH, TocEntry *te); +static int _WriteByte(ArchiveHandle *AH, const int i); +static int _ReadByte(ArchiveHandle *); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _CloseArchive(ArchiveHandle *AH); +static void _ReopenArchive(ArchiveHandle *AH); +static void _PrintTocData(ArchiveHandle *AH, TocEntry *te); +static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te); + +static void _PrintData(ArchiveHandle *AH); +static void _skipData(ArchiveHandle *AH); +static void _skipBlobs(ArchiveHandle *AH); + +static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); +static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlobs(ArchiveHandle *AH, TocEntry *te); +static void _LoadBlobs(ArchiveHandle *AH, bool drop); + +static void _PrepParallelRestore(ArchiveHandle *AH); +static void _Clone(ArchiveHandle *AH); +static void _DeClone(ArchiveHandle *AH); + +static int _WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te); + +typedef struct +{ + CompressorState *cs; + int hasSeek; + /* lastFilePos is used only when reading, and may be invalid if !hasSeek */ + pgoff_t lastFilePos; /* position after last data block we've read */ +} lclContext; + +typedef struct +{ + int dataState; + pgoff_t dataPos; /* valid only if dataState=K_OFFSET_POS_SET */ +} lclTocEntry; + + +/*------ + * Static declarations + *------ + */ +static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id); +static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx); + +static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len); +static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen); + + +/* + * Init routine required by ALL formats. This is a global routine + * and should be declared in pg_backup_archiver.h + * + * It's task is to create any extra archive context (using AH->formatData), + * and to initialize the supported function pointers. + * + * It should also prepare whatever it's input source is for reading/writing, + * and in the case of a read mode connection, it should load the Header & TOC. + */ +void +InitArchiveFmt_Custom(ArchiveHandle *AH) +{ + lclContext *ctx; + + /* Assuming static functions, this can be copied for each format. */ + AH->ArchiveEntryPtr = _ArchiveEntry; + AH->StartDataPtr = _StartData; + AH->WriteDataPtr = _WriteData; + AH->EndDataPtr = _EndData; + AH->WriteBytePtr = _WriteByte; + AH->ReadBytePtr = _ReadByte; + AH->WriteBufPtr = _WriteBuf; + AH->ReadBufPtr = _ReadBuf; + AH->ClosePtr = _CloseArchive; + AH->ReopenPtr = _ReopenArchive; + AH->PrintTocDataPtr = _PrintTocData; + AH->ReadExtraTocPtr = _ReadExtraToc; + AH->WriteExtraTocPtr = _WriteExtraToc; + AH->PrintExtraTocPtr = _PrintExtraToc; + + AH->StartBlobsPtr = _StartBlobs; + AH->StartBlobPtr = _StartBlob; + AH->EndBlobPtr = _EndBlob; + AH->EndBlobsPtr = _EndBlobs; + + AH->PrepParallelRestorePtr = _PrepParallelRestore; + AH->ClonePtr = _Clone; + AH->DeClonePtr = _DeClone; + + /* no parallel dump in the custom archive, only parallel restore */ + AH->WorkerJobDumpPtr = NULL; + AH->WorkerJobRestorePtr = _WorkerJobRestoreCustom; + + /* Set up a private area. */ + ctx = (lclContext *) pg_malloc0(sizeof(lclContext)); + AH->formatData = (void *) ctx; + + /* Initialize LO buffering */ + AH->lo_buf_size = LOBBUFSIZE; + AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE); + + /* + * Now open the file + */ + if (AH->mode == archModeWrite) + { + if (AH->fSpec && strcmp(AH->fSpec, "") != 0) + { + AH->FH = fopen(AH->fSpec, PG_BINARY_W); + if (!AH->FH) + fatal("could not open output file \"%s\": %m", AH->fSpec); + } + else + { + AH->FH = stdout; + if (!AH->FH) + fatal("could not open output file: %m"); + } + + ctx->hasSeek = checkSeek(AH->FH); + } + else + { + if (AH->fSpec && strcmp(AH->fSpec, "") != 0) + { + AH->FH = fopen(AH->fSpec, PG_BINARY_R); + if (!AH->FH) + fatal("could not open input file \"%s\": %m", AH->fSpec); + } + else + { + AH->FH = stdin; + if (!AH->FH) + fatal("could not open input file: %m"); + } + + ctx->hasSeek = checkSeek(AH->FH); + + ReadHead(AH); + ReadToc(AH); + + /* + * Remember location of first data block (i.e., the point after TOC) + * in case we have to search for desired data blocks. + */ + ctx->lastFilePos = _getFilePos(AH, ctx); + } +} + +/* + * Called by the Archiver when the dumper creates a new TOC entry. + * + * Optional. + * + * Set up extract format-related TOC data. +*/ +static void +_ArchiveEntry(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx; + + ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + if (te->dataDumper) + ctx->dataState = K_OFFSET_POS_NOT_SET; + else + ctx->dataState = K_OFFSET_NO_DATA; + + te->formatData = (void *) ctx; +} + +/* + * Called by the Archiver to save any extra format-related TOC entry + * data. + * + * Optional. + * + * Use the Archiver routines to write data - they are non-endian, and + * maintain other important file information. + */ +static void +_WriteExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + WriteOffset(AH, ctx->dataPos, ctx->dataState); +} + +/* + * Called by the Archiver to read any extra format-related TOC data. + * + * Optional. + * + * Needs to match the order defined in _WriteExtraToc, and should also + * use the Archiver input routines. + */ +static void +_ReadExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + if (ctx == NULL) + { + ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + te->formatData = (void *) ctx; + } + + ctx->dataState = ReadOffset(AH, &(ctx->dataPos)); + + /* + * Prior to V1.7 (pg7.3), we dumped the data size as an int now we don't + * dump it at all. + */ + if (AH->version < K_VERS_1_7) + ReadInt(AH); +} + +/* + * Called by the Archiver when restoring an archive to output a comment + * that includes useful information about the TOC entry. + * + * Optional. + */ +static void +_PrintExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + if (AH->public.verbose) + ahprintf(AH, "-- Data Pos: " INT64_FORMAT "\n", + (int64) ctx->dataPos); +} + +/* + * Called by the archiver when saving TABLE DATA (not schema). This routine + * should save whatever format-specific information is needed to read + * the archive back. + * + * It is called just prior to the dumper's 'DataDumper' routine being called. + * + * Optional, but strongly recommended. + * + */ +static void +_StartData(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + tctx->dataPos = _getFilePos(AH, ctx); + if (tctx->dataPos >= 0) + tctx->dataState = K_OFFSET_POS_SET; + + _WriteByte(AH, BLK_DATA); /* Block type */ + WriteInt(AH, te->dumpId); /* For sanity check */ + + ctx->cs = AllocateCompressor(AH->compression, _CustomWriteFunc); +} + +/* + * Called by archiver when dumper calls WriteData. This routine is + * called for both BLOB and TABLE data; it is the responsibility of + * the format to manage each kind of data using StartBlob/StartData. + * + * It should only be called from within a DataDumper routine. + * + * Mandatory. + */ +static void +_WriteData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + lclContext *ctx = (lclContext *) AH->formatData; + CompressorState *cs = ctx->cs; + + if (dLen > 0) + /* WriteDataToArchive() internally throws write errors */ + WriteDataToArchive(AH, cs, data, dLen); +} + +/* + * Called by the archiver when a dumper's 'DataDumper' routine has + * finished. + * + * Optional. + */ +static void +_EndData(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + EndCompressor(AH, ctx->cs); + /* Send the end marker */ + WriteInt(AH, 0); +} + +/* + * Called by the archiver when starting to save all BLOB DATA (not schema). + * This routine should save whatever format-specific information is needed + * to read the BLOBs back into memory. + * + * It is called just prior to the dumper's DataDumper routine. + * + * Optional, but strongly recommended. + */ +static void +_StartBlobs(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + tctx->dataPos = _getFilePos(AH, ctx); + if (tctx->dataPos >= 0) + tctx->dataState = K_OFFSET_POS_SET; + + _WriteByte(AH, BLK_BLOBS); /* Block type */ + WriteInt(AH, te->dumpId); /* For sanity check */ +} + +/* + * Called by the archiver when the dumper calls StartBlob. + * + * Mandatory. + * + * Must save the passed OID for retrieval at restore-time. + */ +static void +_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + if (oid == 0) + fatal("invalid OID for large object"); + + WriteInt(AH, oid); + + ctx->cs = AllocateCompressor(AH->compression, _CustomWriteFunc); +} + +/* + * Called by the archiver when the dumper calls EndBlob. + * + * Optional. + */ +static void +_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + EndCompressor(AH, ctx->cs); + /* Send the end marker */ + WriteInt(AH, 0); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * Optional. + */ +static void +_EndBlobs(ArchiveHandle *AH, TocEntry *te) +{ + /* Write out a fake zero OID to mark end-of-blobs. */ + WriteInt(AH, 0); +} + +/* + * Print data for a given TOC entry + */ +static void +_PrintTocData(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + int blkType; + int id; + + if (tctx->dataState == K_OFFSET_NO_DATA) + return; + + if (!ctx->hasSeek || tctx->dataState == K_OFFSET_POS_NOT_SET) + { + /* + * We cannot seek directly to the desired block. Instead, skip over + * block headers until we find the one we want. Remember the + * positions of skipped-over blocks, so that if we later decide we + * need to read one, we'll be able to seek to it. + * + * When our input file is seekable, we can do the search starting from + * the point after the last data block we scanned in previous + * iterations of this function. + */ + if (ctx->hasSeek) + { + if (fseeko(AH->FH, ctx->lastFilePos, SEEK_SET) != 0) + fatal("error during file seek: %m"); + } + + for (;;) + { + pgoff_t thisBlkPos = _getFilePos(AH, ctx); + + _readBlockHeader(AH, &blkType, &id); + + if (blkType == EOF || id == te->dumpId) + break; + + /* Remember the block position, if we got one */ + if (thisBlkPos >= 0) + { + TocEntry *otherte = getTocEntryByDumpId(AH, id); + + if (otherte && otherte->formatData) + { + lclTocEntry *othertctx = (lclTocEntry *) otherte->formatData; + + /* + * Note: on Windows, multiple threads might access/update + * the same lclTocEntry concurrently, but that should be + * safe as long as we update dataPos before dataState. + * Ideally, we'd use pg_write_barrier() to enforce that, + * but the needed infrastructure doesn't exist in frontend + * code. But Windows only runs on machines with strong + * store ordering, so it should be okay for now. + */ + if (othertctx->dataState == K_OFFSET_POS_NOT_SET) + { + othertctx->dataPos = thisBlkPos; + othertctx->dataState = K_OFFSET_POS_SET; + } + else if (othertctx->dataPos != thisBlkPos || + othertctx->dataState != K_OFFSET_POS_SET) + { + /* sanity check */ + pg_log_warning("data block %d has wrong seek position", + id); + } + } + } + + switch (blkType) + { + case BLK_DATA: + _skipData(AH); + break; + + case BLK_BLOBS: + _skipBlobs(AH); + break; + + default: /* Always have a default */ + fatal("unrecognized data block type (%d) while searching archive", + blkType); + break; + } + } + } + else + { + /* We can just seek to the place we need to be. */ + if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0) + fatal("error during file seek: %m"); + + _readBlockHeader(AH, &blkType, &id); + } + + /* + * If we reached EOF without finding the block we want, then either it + * doesn't exist, or it does but we lack the ability to seek back to it. + */ + if (blkType == EOF) + { + if (!ctx->hasSeek) + fatal("could not find block ID %d in archive -- " + "possibly due to out-of-order restore request, " + "which cannot be handled due to non-seekable input file", + te->dumpId); + else + fatal("could not find block ID %d in archive -- " + "possibly corrupt archive", + te->dumpId); + } + + /* Are we sane? */ + if (id != te->dumpId) + fatal("found unexpected block ID (%d) when reading data -- expected %d", + id, te->dumpId); + + switch (blkType) + { + case BLK_DATA: + _PrintData(AH); + break; + + case BLK_BLOBS: + _LoadBlobs(AH, AH->public.ropt->dropSchema); + break; + + default: /* Always have a default */ + fatal("unrecognized data block type %d while restoring archive", + blkType); + break; + } + + /* + * If our input file is seekable but lacks data offsets, update our + * knowledge of where to start future searches from. (Note that we did + * not update the current TE's dataState/dataPos. We could have, but + * there is no point since it will not be visited again.) + */ + if (ctx->hasSeek && tctx->dataState == K_OFFSET_POS_NOT_SET) + { + pgoff_t curPos = _getFilePos(AH, ctx); + + if (curPos > ctx->lastFilePos) + ctx->lastFilePos = curPos; + } +} + +/* + * Print data from current file position. +*/ +static void +_PrintData(ArchiveHandle *AH) +{ + ReadDataFromArchive(AH, AH->compression, _CustomReadFunc); +} + +static void +_LoadBlobs(ArchiveHandle *AH, bool drop) +{ + Oid oid; + + StartRestoreBlobs(AH); + + oid = ReadInt(AH); + while (oid != 0) + { + StartRestoreBlob(AH, oid, drop); + _PrintData(AH); + EndRestoreBlob(AH, oid); + oid = ReadInt(AH); + } + + EndRestoreBlobs(AH); +} + +/* + * Skip the BLOBs from the current file position. + * BLOBS are written sequentially as data blocks (see below). + * Each BLOB is preceded by its original OID. + * A zero OID indicates the end of the BLOBS. + */ +static void +_skipBlobs(ArchiveHandle *AH) +{ + Oid oid; + + oid = ReadInt(AH); + while (oid != 0) + { + _skipData(AH); + oid = ReadInt(AH); + } +} + +/* + * Skip data from current file position. + * Data blocks are formatted as an integer length, followed by data. + * A zero length indicates the end of the block. +*/ +static void +_skipData(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + size_t blkLen; + char *buf = NULL; + int buflen = 0; + + blkLen = ReadInt(AH); + while (blkLen != 0) + { + if (ctx->hasSeek) + { + if (fseeko(AH->FH, blkLen, SEEK_CUR) != 0) + fatal("error during file seek: %m"); + } + else + { + if (blkLen > buflen) + { + if (buf) + free(buf); + buf = (char *) pg_malloc(blkLen); + buflen = blkLen; + } + if (fread(buf, 1, blkLen, AH->FH) != blkLen) + { + if (feof(AH->FH)) + fatal("could not read from input file: end of file"); + else + fatal("could not read from input file: %m"); + } + } + + blkLen = ReadInt(AH); + } + + if (buf) + free(buf); +} + +/* + * Write a byte of data to the archive. + * + * Mandatory. + * + * Called by the archiver to do integer & byte output to the archive. + */ +static int +_WriteByte(ArchiveHandle *AH, const int i) +{ + if (fputc(i, AH->FH) == EOF) + WRITE_ERROR_EXIT; + + return 1; +} + +/* + * Read a byte of data from the archive. + * + * Mandatory + * + * Called by the archiver to read bytes & integers from the archive. + * EOF should be treated as a fatal error. + */ +static int +_ReadByte(ArchiveHandle *AH) +{ + int res; + + res = getc(AH->FH); + if (res == EOF) + READ_ERROR_EXIT(AH->FH); + return res; +} + +/* + * Write a buffer of data to the archive. + * + * Mandatory. + * + * Called by the archiver to write a block of bytes to the archive. + */ +static void +_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) +{ + if (fwrite(buf, 1, len, AH->FH) != len) + WRITE_ERROR_EXIT; +} + +/* + * Read a block of bytes from the archive. + * + * Mandatory. + * + * Called by the archiver to read a block of bytes from the archive + */ +static void +_ReadBuf(ArchiveHandle *AH, void *buf, size_t len) +{ + if (fread(buf, 1, len, AH->FH) != len) + READ_ERROR_EXIT(AH->FH); +} + +/* + * Close the archive. + * + * Mandatory. + * + * When writing the archive, this is the routine that actually starts + * the process of saving it to files. No data should be written prior + * to this point, since the user could sort the TOC after creating it. + * + * If an archive is to be written, this routine must call: + * WriteHead to save the archive header + * WriteToc to save the TOC entries + * WriteDataChunks to save all DATA & BLOBs. + * + */ +static void +_CloseArchive(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + pgoff_t tpos; + + if (AH->mode == archModeWrite) + { + WriteHead(AH); + /* Remember TOC's seek position for use below */ + tpos = ftello(AH->FH); + if (tpos < 0 && ctx->hasSeek) + fatal("could not determine seek position in archive file: %m"); + WriteToc(AH); + WriteDataChunks(AH, NULL); + + /* + * If possible, re-write the TOC in order to update the data offset + * information. This is not essential, as pg_restore can cope in most + * cases without it; but it can make pg_restore significantly faster + * in some situations (especially parallel restore). + */ + if (ctx->hasSeek && + fseeko(AH->FH, tpos, SEEK_SET) == 0) + WriteToc(AH); + } + + if (fclose(AH->FH) != 0) + fatal("could not close archive file: %m"); + + /* Sync the output file if one is defined */ + if (AH->dosync && AH->mode == archModeWrite && AH->fSpec) + (void) fsync_fname(AH->fSpec, false); + + AH->FH = NULL; +} + +/* + * Reopen the archive's file handle. + * + * We close the original file handle, except on Windows. (The difference + * is because on Windows, this is used within a multithreading context, + * and we don't want a thread closing the parent file handle.) + */ +static void +_ReopenArchive(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + pgoff_t tpos; + + if (AH->mode == archModeWrite) + fatal("can only reopen input archives"); + + /* + * These two cases are user-facing errors since they represent unsupported + * (but not invalid) use-cases. Word the error messages appropriately. + */ + if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0) + fatal("parallel restore from standard input is not supported"); + if (!ctx->hasSeek) + fatal("parallel restore from non-seekable file is not supported"); + + tpos = ftello(AH->FH); + if (tpos < 0) + fatal("could not determine seek position in archive file: %m"); + +#ifndef WIN32 + if (fclose(AH->FH) != 0) + fatal("could not close archive file: %m"); +#endif + + AH->FH = fopen(AH->fSpec, PG_BINARY_R); + if (!AH->FH) + fatal("could not open input file \"%s\": %m", AH->fSpec); + + if (fseeko(AH->FH, tpos, SEEK_SET) != 0) + fatal("could not set seek position in archive file: %m"); +} + +/* + * Prepare for parallel restore. + * + * The main thing that needs to happen here is to fill in TABLE DATA and BLOBS + * TOC entries' dataLength fields with appropriate values to guide the + * ordering of restore jobs. The source of said data is format-dependent, + * as is the exact meaning of the values. + * + * A format module might also choose to do other setup here. + */ +static void +_PrepParallelRestore(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + TocEntry *prev_te = NULL; + lclTocEntry *prev_tctx = NULL; + TocEntry *te; + + /* + * Knowing that the data items were dumped out in TOC order, we can + * reconstruct the length of each item as the delta to the start offset of + * the next data item. + */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + /* + * Ignore entries without a known data offset; if we were unable to + * seek to rewrite the TOC when creating the archive, this'll be all + * of them, and we'll end up with no size estimates. + */ + if (tctx->dataState != K_OFFSET_POS_SET) + continue; + + /* Compute previous data item's length */ + if (prev_te) + { + if (tctx->dataPos > prev_tctx->dataPos) + prev_te->dataLength = tctx->dataPos - prev_tctx->dataPos; + } + + prev_te = te; + prev_tctx = tctx; + } + + /* If OK to seek, we can determine the length of the last item */ + if (prev_te && ctx->hasSeek) + { + pgoff_t endpos; + + if (fseeko(AH->FH, 0, SEEK_END) != 0) + fatal("error during file seek: %m"); + endpos = ftello(AH->FH); + if (endpos > prev_tctx->dataPos) + prev_te->dataLength = endpos - prev_tctx->dataPos; + } +} + +/* + * Clone format-specific fields during parallel restoration. + */ +static void +_Clone(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + /* + * Each thread must have private lclContext working state. + */ + AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext)); + memcpy(AH->formatData, ctx, sizeof(lclContext)); + ctx = (lclContext *) AH->formatData; + + /* sanity check, shouldn't happen */ + if (ctx->cs != NULL) + fatal("compressor active"); + + /* + * We intentionally do not clone TOC-entry-local state: it's useful to + * share knowledge about where the data blocks are across threads. + * _PrintTocData has to be careful about the order of operations on that + * state, though. + * + * Note: we do not make a local lo_buf because we expect at most one BLOBS + * entry per archive, so no parallelism is possible. + */ +} + +static void +_DeClone(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + free(ctx); +} + +/* + * This function is executed in the child of a parallel restore from a + * custom-format archive and restores the actual data for one TOC entry. + */ +static int +_WorkerJobRestoreCustom(ArchiveHandle *AH, TocEntry *te) +{ + return parallel_restore(AH, te); +} + +/*-------------------------------------------------- + * END OF FORMAT CALLBACKS + *-------------------------------------------------- + */ + +/* + * Get the current position in the archive file. + * + * With a non-seekable archive file, we may not be able to obtain the + * file position. If so, just return -1. It's not too important in + * that case because we won't be able to rewrite the TOC to fill in + * data block offsets anyway. + */ +static pgoff_t +_getFilePos(ArchiveHandle *AH, lclContext *ctx) +{ + pgoff_t pos; + + pos = ftello(AH->FH); + if (pos < 0) + { + /* Not expected if we found we can seek. */ + if (ctx->hasSeek) + fatal("could not determine seek position in archive file: %m"); + } + return pos; +} + +/* + * Read a data block header. The format changed in V1.3, so we + * centralize the code here for simplicity. Returns *type = EOF + * if at EOF. + */ +static void +_readBlockHeader(ArchiveHandle *AH, int *type, int *id) +{ + int byt; + + /* + * Note: if we are at EOF with a pre-1.3 input file, we'll fatal() inside + * ReadInt rather than returning EOF. It doesn't seem worth jumping + * through hoops to deal with that case better, because no such files are + * likely to exist in the wild: only some 7.1 development versions of + * pg_dump ever generated such files. + */ + if (AH->version < K_VERS_1_3) + *type = BLK_DATA; + else + { + byt = getc(AH->FH); + *type = byt; + if (byt == EOF) + { + *id = 0; /* don't return an uninitialized value */ + return; + } + } + + *id = ReadInt(AH); +} + +/* + * Callback function for WriteDataToArchive. Writes one block of (compressed) + * data to the archive. + */ +static void +_CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len) +{ + /* never write 0-byte blocks (this should not happen) */ + if (len > 0) + { + WriteInt(AH, len); + _WriteBuf(AH, buf, len); + } +} + +/* + * Callback function for ReadDataFromArchive. To keep things simple, we + * always read one compressed block at a time. + */ +static size_t +_CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen) +{ + size_t blkLen; + + /* Read length */ + blkLen = ReadInt(AH); + if (blkLen == 0) + return 0; + + /* If the caller's buffer is not large enough, allocate a bigger one */ + if (blkLen > *buflen) + { + free(*buf); + *buf = (char *) pg_malloc(blkLen); + *buflen = blkLen; + } + + /* exits app on read errors */ + _ReadBuf(AH, *buf, blkLen); + + return blkLen; +} diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c new file mode 100644 index 0000000..2856c16 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_db.c @@ -0,0 +1,573 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_db.c + * + * Implements the basic DB functions used by the archiver. + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_db.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#include "common/connect.h" +#include "common/string.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" +#include "parallel.h" +#include "pg_backup_archiver.h" +#include "pg_backup_db.h" +#include "pg_backup_utils.h" + +static void _check_database_version(ArchiveHandle *AH); +static void notice_processor(void *arg, const char *message); + +static void +_check_database_version(ArchiveHandle *AH) +{ + const char *remoteversion_str; + int remoteversion; + PGresult *res; + + remoteversion_str = PQparameterStatus(AH->connection, "server_version"); + remoteversion = PQserverVersion(AH->connection); + if (remoteversion == 0 || !remoteversion_str) + fatal("could not get server_version from libpq"); + + AH->public.remoteVersionStr = pg_strdup(remoteversion_str); + AH->public.remoteVersion = remoteversion; + if (!AH->archiveRemoteVersion) + AH->archiveRemoteVersion = AH->public.remoteVersionStr; + + if (remoteversion != PG_VERSION_NUM + && (remoteversion < AH->public.minRemoteVersion || + remoteversion > AH->public.maxRemoteVersion)) + { + pg_log_error("server version: %s; %s version: %s", + remoteversion_str, progname, PG_VERSION); + fatal("aborting because of server version mismatch"); + } + + /* + * When running against 9.0 or later, check if we are in recovery mode, + * which means we are on a hot standby. + */ + if (remoteversion >= 90000) + { + res = ExecuteSqlQueryForSingleRow((Archive *) AH, "SELECT pg_catalog.pg_is_in_recovery()"); + + AH->public.isStandby = (strcmp(PQgetvalue(res, 0, 0), "t") == 0); + PQclear(res); + } + else + AH->public.isStandby = false; +} + +/* + * Reconnect to the server. If dbname is not NULL, use that database, + * else the one associated with the archive handle. + */ +void +ReconnectToServer(ArchiveHandle *AH, const char *dbname) +{ + PGconn *oldConn = AH->connection; + RestoreOptions *ropt = AH->public.ropt; + + /* + * Save the dbname, if given, in override_dbname so that it will also + * affect any later reconnection attempt. + */ + if (dbname) + ropt->cparams.override_dbname = pg_strdup(dbname); + + /* + * Note: we want to establish the new connection, and in particular update + * ArchiveHandle's connCancel, before closing old connection. Otherwise + * an ill-timed SIGINT could try to access a dead connection. + */ + AH->connection = NULL; /* dodge error check in ConnectDatabase */ + + ConnectDatabase((Archive *) AH, &ropt->cparams, true); + + PQfinish(oldConn); +} + +/* + * Make, or remake, a database connection with the given parameters. + * + * The resulting connection handle is stored in AHX->connection. + * + * An interactive password prompt is automatically issued if required. + * We store the results of that in AHX->savedPassword. + * Note: it's not really all that sensible to use a single-entry password + * cache if the username keeps changing. In current usage, however, the + * username never does change, so one savedPassword is sufficient. + */ +void +ConnectDatabase(Archive *AHX, + const ConnParams *cparams, + bool isReconnect) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + trivalue prompt_password; + char *password; + bool new_pass; + + if (AH->connection) + fatal("already connected to a database"); + + /* Never prompt for a password during a reconnection */ + prompt_password = isReconnect ? TRI_NO : cparams->promptPassword; + + password = AH->savedPassword; + + if (prompt_password == TRI_YES && password == NULL) + password = simple_prompt("Password: ", false); + + /* + * Start the connection. Loop until we have a password if requested by + * backend. + */ + do + { + const char *keywords[8]; + const char *values[8]; + int i = 0; + + /* + * If dbname is a connstring, its entries can override the other + * values obtained from cparams; but in turn, override_dbname can + * override the dbname component of it. + */ + keywords[i] = "host"; + values[i++] = cparams->pghost; + keywords[i] = "port"; + values[i++] = cparams->pgport; + keywords[i] = "user"; + values[i++] = cparams->username; + keywords[i] = "password"; + values[i++] = password; + keywords[i] = "dbname"; + values[i++] = cparams->dbname; + if (cparams->override_dbname) + { + keywords[i] = "dbname"; + values[i++] = cparams->override_dbname; + } + keywords[i] = "fallback_application_name"; + values[i++] = progname; + keywords[i] = NULL; + values[i++] = NULL; + Assert(i <= lengthof(keywords)); + + new_pass = false; + AH->connection = PQconnectdbParams(keywords, values, true); + + if (!AH->connection) + fatal("could not connect to database"); + + if (PQstatus(AH->connection) == CONNECTION_BAD && + PQconnectionNeedsPassword(AH->connection) && + password == NULL && + prompt_password != TRI_NO) + { + PQfinish(AH->connection); + password = simple_prompt("Password: ", false); + new_pass = true; + } + } while (new_pass); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(AH->connection) == CONNECTION_BAD) + { + if (isReconnect) + fatal("reconnection failed: %s", + PQerrorMessage(AH->connection)); + else + fatal("%s", + PQerrorMessage(AH->connection)); + } + + /* Start strict; later phases may override this. */ + PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH, + ALWAYS_SECURE_SEARCH_PATH_SQL)); + + if (password && password != AH->savedPassword) + free(password); + + /* + * We want to remember connection's actual password, whether or not we got + * it by prompting. So we don't just store the password variable. + */ + if (PQconnectionUsedPassword(AH->connection)) + { + if (AH->savedPassword) + free(AH->savedPassword); + AH->savedPassword = pg_strdup(PQpass(AH->connection)); + } + + /* check for version mismatch */ + _check_database_version(AH); + + PQsetNoticeProcessor(AH->connection, notice_processor, NULL); + + /* arrange for SIGINT to issue a query cancel on this connection */ + set_archive_cancel_info(AH, AH->connection); +} + +/* + * Close the connection to the database and also cancel off the query if we + * have one running. + */ +void +DisconnectDatabase(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + char errbuf[1]; + + if (!AH->connection) + return; + + if (AH->connCancel) + { + /* + * If we have an active query, send a cancel before closing, ignoring + * any errors. This is of no use for a normal exit, but might be + * helpful during fatal(). + */ + if (PQtransactionStatus(AH->connection) == PQTRANS_ACTIVE) + (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf)); + + /* + * Prevent signal handler from sending a cancel after this. + */ + set_archive_cancel_info(AH, NULL); + } + + PQfinish(AH->connection); + AH->connection = NULL; +} + +PGconn * +GetConnection(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + return AH->connection; +} + +static void +notice_processor(void *arg, const char *message) +{ + pg_log_generic(PG_LOG_INFO, "%s", message); +} + +/* Like fatal(), but with a complaint about a particular query. */ +static void +die_on_query_failure(ArchiveHandle *AH, const char *query) +{ + pg_log_error("query failed: %s", + PQerrorMessage(AH->connection)); + fatal("query was: %s", query); +} + +void +ExecuteSqlStatement(Archive *AHX, const char *query) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + PGresult *res; + + res = PQexec(AH->connection, query); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + die_on_query_failure(AH, query); + PQclear(res); +} + +PGresult * +ExecuteSqlQuery(Archive *AHX, const char *query, ExecStatusType status) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + PGresult *res; + + res = PQexec(AH->connection, query); + if (PQresultStatus(res) != status) + die_on_query_failure(AH, query); + return res; +} + +/* + * Execute an SQL query and verify that we got exactly one row back. + */ +PGresult * +ExecuteSqlQueryForSingleRow(Archive *fout, const char *query) +{ + PGresult *res; + int ntups; + + res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK); + + /* Expecting a single result only */ + ntups = PQntuples(res); + if (ntups != 1) + fatal(ngettext("query returned %d row instead of one: %s", + "query returned %d rows instead of one: %s", + ntups), + ntups, query); + + return res; +} + +/* + * Convenience function to send a query. + * Monitors result to detect COPY statements + */ +static void +ExecuteSqlCommand(ArchiveHandle *AH, const char *qry, const char *desc) +{ + PGconn *conn = AH->connection; + PGresult *res; + +#ifdef NOT_USED + fprintf(stderr, "Executing: '%s'\n\n", qry); +#endif + res = PQexec(conn, qry); + + switch (PQresultStatus(res)) + { + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + case PGRES_EMPTY_QUERY: + /* A-OK */ + break; + case PGRES_COPY_IN: + /* Assume this is an expected result */ + AH->pgCopyIn = true; + break; + default: + /* trouble */ + warn_or_exit_horribly(AH, "%s: %sCommand was: %s", + desc, PQerrorMessage(conn), qry); + break; + } + + PQclear(res); +} + + +/* + * Process non-COPY table data (that is, INSERT commands). + * + * The commands have been run together as one long string for compressibility, + * and we are receiving them in bufferloads with arbitrary boundaries, so we + * have to locate command boundaries and save partial commands across calls. + * All state must be kept in AH->sqlparse, not in local variables of this + * routine. We assume that AH->sqlparse was filled with zeroes when created. + * + * We have to lex the data to the extent of identifying literals and quoted + * identifiers, so that we can recognize statement-terminating semicolons. + * We assume that INSERT data will not contain SQL comments, E'' literals, + * or dollar-quoted strings, so this is much simpler than a full SQL lexer. + * + * Note: when restoring from a pre-9.0 dump file, this code is also used to + * process BLOB COMMENTS data, which has the same problem of containing + * multiple SQL commands that might be split across bufferloads. Fortunately, + * that data won't contain anything complicated to lex either. + */ +static void +ExecuteSimpleCommands(ArchiveHandle *AH, const char *buf, size_t bufLen) +{ + const char *qry = buf; + const char *eos = buf + bufLen; + + /* initialize command buffer if first time through */ + if (AH->sqlparse.curCmd == NULL) + AH->sqlparse.curCmd = createPQExpBuffer(); + + for (; qry < eos; qry++) + { + char ch = *qry; + + /* For neatness, we skip any newlines between commands */ + if (!(ch == '\n' && AH->sqlparse.curCmd->len == 0)) + appendPQExpBufferChar(AH->sqlparse.curCmd, ch); + + switch (AH->sqlparse.state) + { + case SQL_SCAN: /* Default state == 0, set in _allocAH */ + if (ch == ';') + { + /* + * We've found the end of a statement. Send it and reset + * the buffer. + */ + ExecuteSqlCommand(AH, AH->sqlparse.curCmd->data, + "could not execute query"); + resetPQExpBuffer(AH->sqlparse.curCmd); + } + else if (ch == '\'') + { + AH->sqlparse.state = SQL_IN_SINGLE_QUOTE; + AH->sqlparse.backSlash = false; + } + else if (ch == '"') + { + AH->sqlparse.state = SQL_IN_DOUBLE_QUOTE; + } + break; + + case SQL_IN_SINGLE_QUOTE: + /* We needn't handle '' specially */ + if (ch == '\'' && !AH->sqlparse.backSlash) + AH->sqlparse.state = SQL_SCAN; + else if (ch == '\\' && !AH->public.std_strings) + AH->sqlparse.backSlash = !AH->sqlparse.backSlash; + else + AH->sqlparse.backSlash = false; + break; + + case SQL_IN_DOUBLE_QUOTE: + /* We needn't handle "" specially */ + if (ch == '"') + AH->sqlparse.state = SQL_SCAN; + break; + } + } +} + + +/* + * Implement ahwrite() for direct-to-DB restore + */ +int +ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + if (AH->outputKind == OUTPUT_COPYDATA) + { + /* + * COPY data. + * + * We drop the data on the floor if libpq has failed to enter COPY + * mode; this allows us to behave reasonably when trying to continue + * after an error in a COPY command. + */ + if (AH->pgCopyIn && + PQputCopyData(AH->connection, buf, bufLen) <= 0) + fatal("error returned by PQputCopyData: %s", + PQerrorMessage(AH->connection)); + } + else if (AH->outputKind == OUTPUT_OTHERDATA) + { + /* + * Table data expressed as INSERT commands; or, in old dump files, + * BLOB COMMENTS data (which is expressed as COMMENT ON commands). + */ + ExecuteSimpleCommands(AH, buf, bufLen); + } + else + { + /* + * General SQL commands; we assume that commands will not be split + * across calls. + * + * In most cases the data passed to us will be a null-terminated + * string, but if it's not, we have to add a trailing null. + */ + if (buf[bufLen] == '\0') + ExecuteSqlCommand(AH, buf, "could not execute query"); + else + { + char *str = (char *) pg_malloc(bufLen + 1); + + memcpy(str, buf, bufLen); + str[bufLen] = '\0'; + ExecuteSqlCommand(AH, str, "could not execute query"); + free(str); + } + } + + return bufLen; +} + +/* + * Terminate a COPY operation during direct-to-DB restore + */ +void +EndDBCopyMode(Archive *AHX, const char *tocEntryTag) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + if (AH->pgCopyIn) + { + PGresult *res; + + if (PQputCopyEnd(AH->connection, NULL) <= 0) + fatal("error returned by PQputCopyEnd: %s", + PQerrorMessage(AH->connection)); + + /* Check command status and return to normal libpq state */ + res = PQgetResult(AH->connection); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + warn_or_exit_horribly(AH, "COPY failed for table \"%s\": %s", + tocEntryTag, PQerrorMessage(AH->connection)); + PQclear(res); + + /* Do this to ensure we've pumped libpq back to idle state */ + if (PQgetResult(AH->connection) != NULL) + pg_log_warning("unexpected extra results during COPY of table \"%s\"", + tocEntryTag); + + AH->pgCopyIn = false; + } +} + +void +StartTransaction(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + ExecuteSqlCommand(AH, "BEGIN", "could not start database transaction"); +} + +void +CommitTransaction(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + + ExecuteSqlCommand(AH, "COMMIT", "could not commit database transaction"); +} + +void +DropBlobIfExists(ArchiveHandle *AH, Oid oid) +{ + /* + * If we are not restoring to a direct database connection, we have to + * guess about how to detect whether the blob exists. Assume new-style. + */ + if (AH->connection == NULL || + PQserverVersion(AH->connection) >= 90000) + { + ahprintf(AH, + "SELECT pg_catalog.lo_unlink(oid) " + "FROM pg_catalog.pg_largeobject_metadata " + "WHERE oid = '%u';\n", + oid); + } + else + { + /* Restoring to pre-9.0 server, so do it the old way */ + ahprintf(AH, + "SELECT CASE WHEN EXISTS(" + "SELECT 1 FROM pg_catalog.pg_largeobject WHERE loid = '%u'" + ") THEN pg_catalog.lo_unlink('%u') END;\n", + oid, oid); + } +} diff --git a/src/bin/pg_dump/pg_backup_db.h b/src/bin/pg_dump/pg_backup_db.h new file mode 100644 index 0000000..8888dd3 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_db.h @@ -0,0 +1,26 @@ +/* + * Definitions for pg_backup_db.c + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_db.h + */ + +#ifndef PG_BACKUP_DB_H +#define PG_BACKUP_DB_H + +#include "pg_backup.h" + + +extern int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen); + +extern void ExecuteSqlStatement(Archive *AHX, const char *query); +extern PGresult *ExecuteSqlQuery(Archive *AHX, const char *query, + ExecStatusType status); +extern PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, const char *query); + +extern void EndDBCopyMode(Archive *AHX, const char *tocEntryTag); + +extern void StartTransaction(Archive *AHX); +extern void CommitTransaction(Archive *AHX); + +#endif diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c new file mode 100644 index 0000000..4e0fb7d --- /dev/null +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -0,0 +1,851 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_directory.c + * + * A directory format dump is a directory, which contains a "toc.dat" file + * for the TOC, and a separate file for each data entry, named ".dat". + * Large objects (BLOBs) are stored in separate files named "blob_.dat", + * and there's a plain-text TOC file for them called "blobs.toc". If + * compression is used, each data file is individually compressed and the + * ".gz" suffix is added to the filenames. The TOC files are never + * compressed by pg_dump, however they are accepted with the .gz suffix too, + * in case the user has manually compressed them with 'gzip'. + * + * NOTE: This format is identical to the files written in the tar file in + * the 'tar' format, except that we don't write the restore.sql file (TODO), + * and the tar format doesn't support compression. Please keep the formats in + * sync. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2000, Philip Warner + * + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_directory.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#include + +#include "common/file_utils.h" +#include "compress_io.h" +#include "parallel.h" +#include "pg_backup_utils.h" + +typedef struct +{ + /* + * Our archive location. This is basically what the user specified as his + * backup file but of course here it is a directory. + */ + char *directory; + + cfp *dataFH; /* currently open data file */ + + cfp *blobsTocFH; /* file handle for blobs.toc */ + ParallelState *pstate; /* for parallel backup / restore */ +} lclContext; + +typedef struct +{ + char *filename; /* filename excluding the directory (basename) */ +} lclTocEntry; + +/* prototypes for private functions */ +static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); +static void _StartData(ArchiveHandle *AH, TocEntry *te); +static void _EndData(ArchiveHandle *AH, TocEntry *te); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static int _WriteByte(ArchiveHandle *AH, const int i); +static int _ReadByte(ArchiveHandle *); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _CloseArchive(ArchiveHandle *AH); +static void _ReopenArchive(ArchiveHandle *AH); +static void _PrintTocData(ArchiveHandle *AH, TocEntry *te); + +static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te); + +static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); +static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlobs(ArchiveHandle *AH, TocEntry *te); +static void _LoadBlobs(ArchiveHandle *AH); + +static void _PrepParallelRestore(ArchiveHandle *AH); +static void _Clone(ArchiveHandle *AH); +static void _DeClone(ArchiveHandle *AH); + +static int _WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te); +static int _WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te); + +static void setFilePath(ArchiveHandle *AH, char *buf, + const char *relativeFilename); + +/* + * Init routine required by ALL formats. This is a global routine + * and should be declared in pg_backup_archiver.h + * + * Its task is to create any extra archive context (using AH->formatData), + * and to initialize the supported function pointers. + * + * It should also prepare whatever its input source is for reading/writing, + * and in the case of a read mode connection, it should load the Header & TOC. + */ +void +InitArchiveFmt_Directory(ArchiveHandle *AH) +{ + lclContext *ctx; + + /* Assuming static functions, this can be copied for each format. */ + AH->ArchiveEntryPtr = _ArchiveEntry; + AH->StartDataPtr = _StartData; + AH->WriteDataPtr = _WriteData; + AH->EndDataPtr = _EndData; + AH->WriteBytePtr = _WriteByte; + AH->ReadBytePtr = _ReadByte; + AH->WriteBufPtr = _WriteBuf; + AH->ReadBufPtr = _ReadBuf; + AH->ClosePtr = _CloseArchive; + AH->ReopenPtr = _ReopenArchive; + AH->PrintTocDataPtr = _PrintTocData; + AH->ReadExtraTocPtr = _ReadExtraToc; + AH->WriteExtraTocPtr = _WriteExtraToc; + AH->PrintExtraTocPtr = _PrintExtraToc; + + AH->StartBlobsPtr = _StartBlobs; + AH->StartBlobPtr = _StartBlob; + AH->EndBlobPtr = _EndBlob; + AH->EndBlobsPtr = _EndBlobs; + + AH->PrepParallelRestorePtr = _PrepParallelRestore; + AH->ClonePtr = _Clone; + AH->DeClonePtr = _DeClone; + + AH->WorkerJobRestorePtr = _WorkerJobRestoreDirectory; + AH->WorkerJobDumpPtr = _WorkerJobDumpDirectory; + + /* Set up our private context */ + ctx = (lclContext *) pg_malloc0(sizeof(lclContext)); + AH->formatData = (void *) ctx; + + ctx->dataFH = NULL; + ctx->blobsTocFH = NULL; + + /* Initialize LO buffering */ + AH->lo_buf_size = LOBBUFSIZE; + AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE); + + /* + * Now open the TOC file + */ + + if (!AH->fSpec || strcmp(AH->fSpec, "") == 0) + fatal("no output directory specified"); + + ctx->directory = AH->fSpec; + + if (AH->mode == archModeWrite) + { + struct stat st; + bool is_empty = false; + + /* we accept an empty existing directory */ + if (stat(ctx->directory, &st) == 0 && S_ISDIR(st.st_mode)) + { + DIR *dir = opendir(ctx->directory); + + if (dir) + { + struct dirent *d; + + is_empty = true; + while (errno = 0, (d = readdir(dir))) + { + if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) + { + is_empty = false; + break; + } + } + + if (errno) + fatal("could not read directory \"%s\": %m", + ctx->directory); + + if (closedir(dir)) + fatal("could not close directory \"%s\": %m", + ctx->directory); + } + } + + if (!is_empty && mkdir(ctx->directory, 0700) < 0) + fatal("could not create directory \"%s\": %m", + ctx->directory); + } + else + { /* Read Mode */ + char fname[MAXPGPATH]; + cfp *tocFH; + + setFilePath(AH, fname, "toc.dat"); + + tocFH = cfopen_read(fname, PG_BINARY_R); + if (tocFH == NULL) + fatal("could not open input file \"%s\": %m", fname); + + ctx->dataFH = tocFH; + + /* + * The TOC of a directory format dump shares the format code of the + * tar format. + */ + AH->format = archTar; + ReadHead(AH); + AH->format = archDirectory; + ReadToc(AH); + + /* Nothing else in the file, so close it again... */ + if (cfclose(tocFH) != 0) + fatal("could not close TOC file: %m"); + ctx->dataFH = NULL; + } +} + +/* + * Called by the Archiver when the dumper creates a new TOC entry. + * + * We determine the filename for this entry. +*/ +static void +_ArchiveEntry(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx; + char fn[MAXPGPATH]; + + tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + if (strcmp(te->desc, "BLOBS") == 0) + tctx->filename = pg_strdup("blobs.toc"); + else if (te->dataDumper) + { + snprintf(fn, MAXPGPATH, "%d.dat", te->dumpId); + tctx->filename = pg_strdup(fn); + } + else + tctx->filename = NULL; + + te->formatData = (void *) tctx; +} + +/* + * Called by the Archiver to save any extra format-related TOC entry + * data. + * + * Use the Archiver routines to write data - they are non-endian, and + * maintain other important file information. + */ +static void +_WriteExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + /* + * A dumpable object has set tctx->filename, any other object has not. + * (see _ArchiveEntry). + */ + if (tctx->filename) + WriteStr(AH, tctx->filename); + else + WriteStr(AH, ""); +} + +/* + * Called by the Archiver to read any extra format-related TOC data. + * + * Needs to match the order defined in _WriteExtraToc, and should also + * use the Archiver input routines. + */ +static void +_ReadExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + if (tctx == NULL) + { + tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + te->formatData = (void *) tctx; + } + + tctx->filename = ReadStr(AH); + if (strlen(tctx->filename) == 0) + { + free(tctx->filename); + tctx->filename = NULL; + } +} + +/* + * Called by the Archiver when restoring an archive to output a comment + * that includes useful information about the TOC entry. + */ +static void +_PrintExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + if (AH->public.verbose && tctx->filename) + ahprintf(AH, "-- File: %s\n", tctx->filename); +} + +/* + * Called by the archiver when saving TABLE DATA (not schema). This routine + * should save whatever format-specific information is needed to read + * the archive back. + * + * It is called just prior to the dumper's 'DataDumper' routine being called. + * + * We create the data file for writing. + */ +static void +_StartData(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + lclContext *ctx = (lclContext *) AH->formatData; + char fname[MAXPGPATH]; + + setFilePath(AH, fname, tctx->filename); + + ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression); + if (ctx->dataFH == NULL) + fatal("could not open output file \"%s\": %m", fname); +} + +/* + * Called by archiver when dumper calls WriteData. This routine is + * called for both BLOB and TABLE data; it is the responsibility of + * the format to manage each kind of data using StartBlob/StartData. + * + * It should only be called from within a DataDumper routine. + * + * We write the data to the open data file. + */ +static void +_WriteData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + errno = 0; + if (dLen > 0 && cfwrite(data, dLen, ctx->dataFH) != dLen) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; + fatal("could not write to output file: %s", + get_cfp_error(ctx->dataFH)); + } +} + +/* + * Called by the archiver when a dumper's 'DataDumper' routine has + * finished. + * + * We close the data file. + */ +static void +_EndData(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + /* Close the file */ + if (cfclose(ctx->dataFH) != 0) + fatal("could not close data file: %m"); + + ctx->dataFH = NULL; +} + +/* + * Print data for a given file (can be a BLOB as well) + */ +static void +_PrintFileData(ArchiveHandle *AH, char *filename) +{ + size_t cnt; + char *buf; + size_t buflen; + cfp *cfp; + + if (!filename) + return; + + cfp = cfopen_read(filename, PG_BINARY_R); + + if (!cfp) + fatal("could not open input file \"%s\": %m", filename); + + buf = pg_malloc(ZLIB_OUT_SIZE); + buflen = ZLIB_OUT_SIZE; + + while ((cnt = cfread(buf, buflen, cfp))) + { + ahwrite(buf, 1, cnt, AH); + } + + free(buf); + if (cfclose(cfp) != 0) + fatal("could not close data file \"%s\": %m", filename); +} + +/* + * Print data for a given TOC entry +*/ +static void +_PrintTocData(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + if (!tctx->filename) + return; + + if (strcmp(te->desc, "BLOBS") == 0) + _LoadBlobs(AH); + else + { + char fname[MAXPGPATH]; + + setFilePath(AH, fname, tctx->filename); + _PrintFileData(AH, fname); + } +} + +static void +_LoadBlobs(ArchiveHandle *AH) +{ + Oid oid; + lclContext *ctx = (lclContext *) AH->formatData; + char tocfname[MAXPGPATH]; + char line[MAXPGPATH]; + + StartRestoreBlobs(AH); + + setFilePath(AH, tocfname, "blobs.toc"); + + ctx->blobsTocFH = cfopen_read(tocfname, PG_BINARY_R); + + if (ctx->blobsTocFH == NULL) + fatal("could not open large object TOC file \"%s\" for input: %m", + tocfname); + + /* Read the blobs TOC file line-by-line, and process each blob */ + while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL) + { + char blobfname[MAXPGPATH + 1]; + char path[MAXPGPATH]; + + /* Can't overflow because line and blobfname are the same length */ + if (sscanf(line, "%u %" CppAsString2(MAXPGPATH) "s\n", &oid, blobfname) != 2) + fatal("invalid line in large object TOC file \"%s\": \"%s\"", + tocfname, line); + + StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema); + snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, blobfname); + _PrintFileData(AH, path); + EndRestoreBlob(AH, oid); + } + if (!cfeof(ctx->blobsTocFH)) + fatal("error reading large object TOC file \"%s\"", + tocfname); + + if (cfclose(ctx->blobsTocFH) != 0) + fatal("could not close large object TOC file \"%s\": %m", + tocfname); + + ctx->blobsTocFH = NULL; + + EndRestoreBlobs(AH); +} + + +/* + * Write a byte of data to the archive. + * Called by the archiver to do integer & byte output to the archive. + * These routines are only used to read & write the headers & TOC. + */ +static int +_WriteByte(ArchiveHandle *AH, const int i) +{ + unsigned char c = (unsigned char) i; + lclContext *ctx = (lclContext *) AH->formatData; + + errno = 0; + if (cfwrite(&c, 1, ctx->dataFH) != 1) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; + fatal("could not write to output file: %s", + get_cfp_error(ctx->dataFH)); + } + + return 1; +} + +/* + * Read a byte of data from the archive. + * Called by the archiver to read bytes & integers from the archive. + * These routines are only used to read & write headers & TOC. + * EOF should be treated as a fatal error. + */ +static int +_ReadByte(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + return cfgetc(ctx->dataFH); +} + +/* + * Write a buffer of data to the archive. + * Called by the archiver to write a block of bytes to the TOC or a data file. + */ +static void +_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + errno = 0; + if (cfwrite(buf, len, ctx->dataFH) != len) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; + fatal("could not write to output file: %s", + get_cfp_error(ctx->dataFH)); + } +} + +/* + * Read a block of bytes from the archive. + * + * Called by the archiver to read a block of bytes from the archive + */ +static void +_ReadBuf(ArchiveHandle *AH, void *buf, size_t len) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + /* + * If there was an I/O error, we already exited in cfread(), so here we + * exit on short reads. + */ + if (cfread(buf, len, ctx->dataFH) != len) + fatal("could not read from input file: end of file"); +} + +/* + * Close the archive. + * + * When writing the archive, this is the routine that actually starts + * the process of saving it to files. No data should be written prior + * to this point, since the user could sort the TOC after creating it. + * + * If an archive is to be written, this routine must call: + * WriteHead to save the archive header + * WriteToc to save the TOC entries + * WriteDataChunks to save all DATA & BLOBs. + */ +static void +_CloseArchive(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + if (AH->mode == archModeWrite) + { + cfp *tocFH; + char fname[MAXPGPATH]; + + setFilePath(AH, fname, "toc.dat"); + + /* this will actually fork the processes for a parallel backup */ + ctx->pstate = ParallelBackupStart(AH); + + /* The TOC is always created uncompressed */ + tocFH = cfopen_write(fname, PG_BINARY_W, 0); + if (tocFH == NULL) + fatal("could not open output file \"%s\": %m", fname); + ctx->dataFH = tocFH; + + /* + * Write 'tar' in the format field of the toc.dat file. The directory + * is compatible with 'tar', so there's no point having a different + * format code for it. + */ + AH->format = archTar; + WriteHead(AH); + AH->format = archDirectory; + WriteToc(AH); + if (cfclose(tocFH) != 0) + fatal("could not close TOC file: %m"); + WriteDataChunks(AH, ctx->pstate); + + ParallelBackupEnd(AH, ctx->pstate); + + /* + * In directory mode, there is no need to sync all the entries + * individually. Just recurse once through all the files generated. + */ + if (AH->dosync) + fsync_dir_recurse(ctx->directory); + } + AH->FH = NULL; +} + +/* + * Reopen the archive's file handle. + */ +static void +_ReopenArchive(ArchiveHandle *AH) +{ + /* + * Our TOC is in memory, our data files are opened by each child anyway as + * they are separate. We support reopening the archive by just doing + * nothing. + */ +} + +/* + * BLOB support + */ + +/* + * Called by the archiver when starting to save all BLOB DATA (not schema). + * It is called just prior to the dumper's DataDumper routine. + * + * We open the large object TOC file here, so that we can append a line to + * it for each blob. + */ +static void +_StartBlobs(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char fname[MAXPGPATH]; + + setFilePath(AH, fname, "blobs.toc"); + + /* The blob TOC file is never compressed */ + ctx->blobsTocFH = cfopen_write(fname, "ab", 0); + if (ctx->blobsTocFH == NULL) + fatal("could not open output file \"%s\": %m", fname); +} + +/* + * Called by the archiver when we're about to start dumping a blob. + * + * We create a file to write the blob to. + */ +static void +_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char fname[MAXPGPATH]; + + snprintf(fname, MAXPGPATH, "%s/blob_%u.dat", ctx->directory, oid); + + ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression); + + if (ctx->dataFH == NULL) + fatal("could not open output file \"%s\": %m", fname); +} + +/* + * Called by the archiver when the dumper is finished writing a blob. + * + * We close the blob file and write an entry to the blob TOC file for it. + */ +static void +_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char buf[50]; + int len; + + /* Close the BLOB data file itself */ + if (cfclose(ctx->dataFH) != 0) + fatal("could not close blob data file: %m"); + ctx->dataFH = NULL; + + /* register the blob in blobs.toc */ + len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid); + if (cfwrite(buf, len, ctx->blobsTocFH) != len) + fatal("could not write to blobs TOC file"); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * We close the blobs TOC file. + */ +static void +_EndBlobs(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + if (cfclose(ctx->blobsTocFH) != 0) + fatal("could not close blobs TOC file: %m"); + ctx->blobsTocFH = NULL; +} + +/* + * Gets a relative file name and prepends the output directory, writing the + * result to buf. The caller needs to make sure that buf is MAXPGPATH bytes + * big. Can't use a static char[MAXPGPATH] inside the function because we run + * multithreaded on Windows. + */ +static void +setFilePath(ArchiveHandle *AH, char *buf, const char *relativeFilename) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char *dname; + + dname = ctx->directory; + + if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH) + fatal("file name too long: \"%s\"", dname); + + strcpy(buf, dname); + strcat(buf, "/"); + strcat(buf, relativeFilename); +} + +/* + * Prepare for parallel restore. + * + * The main thing that needs to happen here is to fill in TABLE DATA and BLOBS + * TOC entries' dataLength fields with appropriate values to guide the + * ordering of restore jobs. The source of said data is format-dependent, + * as is the exact meaning of the values. + * + * A format module might also choose to do other setup here. + */ +static void +_PrepParallelRestore(ArchiveHandle *AH) +{ + TocEntry *te; + + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + char fname[MAXPGPATH]; + struct stat st; + + /* + * A dumpable object has set tctx->filename, any other object has not. + * (see _ArchiveEntry). + */ + if (tctx->filename == NULL) + continue; + + /* We may ignore items not due to be restored */ + if ((te->reqs & REQ_DATA) == 0) + continue; + + /* + * Stat the file and, if successful, put its size in dataLength. When + * using compression, the physical file size might not be a very good + * guide to the amount of work involved in restoring the file, but we + * only need an approximate indicator of that. + */ + setFilePath(AH, fname, tctx->filename); + + if (stat(fname, &st) == 0) + te->dataLength = st.st_size; + else + { + /* It might be compressed */ + strlcat(fname, ".gz", sizeof(fname)); + if (stat(fname, &st) == 0) + te->dataLength = st.st_size; + } + + /* + * If this is the BLOBS entry, what we stat'd was blobs.toc, which + * most likely is a lot smaller than the actual blob data. We don't + * have a cheap way to estimate how much smaller, but fortunately it + * doesn't matter too much as long as we get the blobs processed + * reasonably early. Arbitrarily scale up by a factor of 1K. + */ + if (strcmp(te->desc, "BLOBS") == 0) + te->dataLength *= 1024; + } +} + +/* + * Clone format-specific fields during parallel restoration. + */ +static void +_Clone(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + AH->formatData = (lclContext *) pg_malloc(sizeof(lclContext)); + memcpy(AH->formatData, ctx, sizeof(lclContext)); + ctx = (lclContext *) AH->formatData; + + /* + * Note: we do not make a local lo_buf because we expect at most one BLOBS + * entry per archive, so no parallelism is possible. Likewise, + * TOC-entry-local state isn't an issue because any one TOC entry is + * touched by just one worker child. + */ + + /* + * We also don't copy the ParallelState pointer (pstate), only the leader + * process ever writes to it. + */ +} + +static void +_DeClone(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + free(ctx); +} + +/* + * This function is executed in the child of a parallel backup for a + * directory-format archive and dumps the actual data for one TOC entry. + */ +static int +_WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te) +{ + /* + * This function returns void. We either fail and die horribly or + * succeed... A failure will be detected by the parent when the child dies + * unexpectedly. + */ + WriteDataChunksForTocEntry(AH, te); + + return 0; +} + +/* + * This function is executed in the child of a parallel restore from a + * directory-format archive and restores the actual data for one TOC entry. + */ +static int +_WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te) +{ + return parallel_restore(AH, te); +} diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c new file mode 100644 index 0000000..0458979 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_null.c @@ -0,0 +1,228 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_null.c + * + * Implementation of an archive that is never saved; it is used by + * pg_dump to output a plain text SQL script instead of saving + * a real archive. + * + * See the headers to pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_null.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "fe_utils/string_utils.h" +#include "libpq/libpq-fs.h" +#include "pg_backup_archiver.h" +#include "pg_backup_utils.h" + +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _EndData(ArchiveHandle *AH, TocEntry *te); +static int _WriteByte(ArchiveHandle *AH, const int i); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _CloseArchive(ArchiveHandle *AH); +static void _PrintTocData(ArchiveHandle *AH, TocEntry *te); +static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); +static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlobs(ArchiveHandle *AH, TocEntry *te); + + +/* + * Initializer + */ +void +InitArchiveFmt_Null(ArchiveHandle *AH) +{ + /* Assuming static functions, this can be copied for each format. */ + AH->WriteDataPtr = _WriteData; + AH->EndDataPtr = _EndData; + AH->WriteBytePtr = _WriteByte; + AH->WriteBufPtr = _WriteBuf; + AH->ClosePtr = _CloseArchive; + AH->ReopenPtr = NULL; + AH->PrintTocDataPtr = _PrintTocData; + + AH->StartBlobsPtr = _StartBlobs; + AH->StartBlobPtr = _StartBlob; + AH->EndBlobPtr = _EndBlob; + AH->EndBlobsPtr = _EndBlobs; + AH->ClonePtr = NULL; + AH->DeClonePtr = NULL; + + /* Initialize LO buffering */ + AH->lo_buf_size = LOBBUFSIZE; + AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE); + + /* + * Now prevent reading... + */ + if (AH->mode == archModeRead) + fatal("this format cannot be read"); +} + +/* + * - Start a new TOC entry + */ + +/* + * Called by dumper via archiver from within a data dump routine + */ +static void +_WriteData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + /* Just send it to output, ahwrite() already errors on failure */ + ahwrite(data, 1, dLen, AH); +} + +/* + * Called by dumper via archiver from within a data dump routine + * We substitute this for _WriteData while emitting a BLOB + */ +static void +_WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + if (dLen > 0) + { + PQExpBuffer buf = createPQExpBuffer(); + + appendByteaLiteralAHX(buf, + (const unsigned char *) data, + dLen, + AH); + + ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data); + + destroyPQExpBuffer(buf); + } +} + +static void +_EndData(ArchiveHandle *AH, TocEntry *te) +{ + ahprintf(AH, "\n\n"); +} + +/* + * Called by the archiver when starting to save all BLOB DATA (not schema). + * This routine should save whatever format-specific information is needed + * to read the BLOBs back into memory. + * + * It is called just prior to the dumper's DataDumper routine. + * + * Optional, but strongly recommended. + */ +static void +_StartBlobs(ArchiveHandle *AH, TocEntry *te) +{ + ahprintf(AH, "BEGIN;\n\n"); +} + +/* + * Called by the archiver when the dumper calls StartBlob. + * + * Mandatory. + * + * Must save the passed OID for retrieval at restore-time. + */ +static void +_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + bool old_blob_style = (AH->version < K_VERS_1_12); + + if (oid == 0) + fatal("invalid OID for large object"); + + /* With an old archive we must do drop and create logic here */ + if (old_blob_style && AH->public.ropt->dropSchema) + DropBlobIfExists(AH, oid); + + if (old_blob_style) + ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n", + oid, INV_WRITE); + else + ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n", + oid, INV_WRITE); + + AH->WriteDataPtr = _WriteBlobData; +} + +/* + * Called by the archiver when the dumper calls EndBlob. + * + * Optional. + */ +static void +_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + AH->WriteDataPtr = _WriteData; + + ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n"); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * Optional. + */ +static void +_EndBlobs(ArchiveHandle *AH, TocEntry *te) +{ + ahprintf(AH, "COMMIT;\n\n"); +} + +/*------ + * Called as part of a RestoreArchive call; for the NULL archive, this + * just sends the data for a given TOC entry to the output. + *------ + */ +static void +_PrintTocData(ArchiveHandle *AH, TocEntry *te) +{ + if (te->dataDumper) + { + AH->currToc = te; + + if (strcmp(te->desc, "BLOBS") == 0) + _StartBlobs(AH, te); + + te->dataDumper((Archive *) AH, te->dataDumperArg); + + if (strcmp(te->desc, "BLOBS") == 0) + _EndBlobs(AH, te); + + AH->currToc = NULL; + } +} + +static int +_WriteByte(ArchiveHandle *AH, const int i) +{ + /* Don't do anything */ + return 0; +} + +static void +_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) +{ + /* Don't do anything */ +} + +static void +_CloseArchive(ArchiveHandle *AH) +{ + /* Nothing to do */ +} diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c new file mode 100644 index 0000000..5c351ac --- /dev/null +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -0,0 +1,1306 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_tar.c + * + * This file is copied from the 'files' format file, but dumps data into + * one temp file then sends it to the output TAR archive. + * + * The tar format also includes a 'restore.sql' script which is there for + * the benefit of humans. This script is never used by pg_restore. + * + * NOTE: If you untar the created 'tar' file, the resulting files are + * compatible with the 'directory' format. Please keep the two formats in + * sync. + * + * See the headers to pg_backup_directory & pg_restore for more details. + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_backup_tar.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#include +#include +#include + +#include "common/file_utils.h" +#include "fe_utils/string_utils.h" +#include "pg_backup_archiver.h" +#include "pg_backup_tar.h" +#include "pg_backup_utils.h" +#include "pgtar.h" + +static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); +static void _StartData(ArchiveHandle *AH, TocEntry *te); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _EndData(ArchiveHandle *AH, TocEntry *te); +static int _WriteByte(ArchiveHandle *AH, const int i); +static int _ReadByte(ArchiveHandle *); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _CloseArchive(ArchiveHandle *AH); +static void _PrintTocData(ArchiveHandle *AH, TocEntry *te); +static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te); +static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te); + +static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); +static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid); +static void _EndBlobs(ArchiveHandle *AH, TocEntry *te); + +#define K_STD_BUF_SIZE 1024 + + +typedef struct +{ +#ifdef HAVE_LIBZ + gzFile zFH; +#else + FILE *zFH; +#endif + FILE *nFH; + FILE *tarFH; + FILE *tmpFH; + char *targetFile; + char mode; + pgoff_t pos; + pgoff_t fileLen; + ArchiveHandle *AH; +} TAR_MEMBER; + +typedef struct +{ + int hasSeek; + pgoff_t filePos; + TAR_MEMBER *blobToc; + FILE *tarFH; + pgoff_t tarFHpos; + pgoff_t tarNextMember; + TAR_MEMBER *FH; + int isSpecialScript; + TAR_MEMBER *scriptTH; +} lclContext; + +typedef struct +{ + TAR_MEMBER *TH; + char *filename; +} lclTocEntry; + +static void _LoadBlobs(ArchiveHandle *AH); + +static TAR_MEMBER *tarOpen(ArchiveHandle *AH, const char *filename, char mode); +static void tarClose(ArchiveHandle *AH, TAR_MEMBER *TH); + +#ifdef __NOT_USED__ +static char *tarGets(char *buf, size_t len, TAR_MEMBER *th); +#endif +static int tarPrintf(TAR_MEMBER *th, const char *fmt,...) pg_attribute_printf(2, 3); + +static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th); +static TAR_MEMBER *_tarPositionTo(ArchiveHandle *AH, const char *filename); +static size_t tarRead(void *buf, size_t len, TAR_MEMBER *th); +static size_t tarWrite(const void *buf, size_t len, TAR_MEMBER *th); +static void _tarWriteHeader(TAR_MEMBER *th); +static int _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th); +static size_t _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh); + +static size_t _scriptOut(ArchiveHandle *AH, const void *buf, size_t len); + +/* + * Initializer + */ +void +InitArchiveFmt_Tar(ArchiveHandle *AH) +{ + lclContext *ctx; + + /* Assuming static functions, this can be copied for each format. */ + AH->ArchiveEntryPtr = _ArchiveEntry; + AH->StartDataPtr = _StartData; + AH->WriteDataPtr = _WriteData; + AH->EndDataPtr = _EndData; + AH->WriteBytePtr = _WriteByte; + AH->ReadBytePtr = _ReadByte; + AH->WriteBufPtr = _WriteBuf; + AH->ReadBufPtr = _ReadBuf; + AH->ClosePtr = _CloseArchive; + AH->ReopenPtr = NULL; + AH->PrintTocDataPtr = _PrintTocData; + AH->ReadExtraTocPtr = _ReadExtraToc; + AH->WriteExtraTocPtr = _WriteExtraToc; + AH->PrintExtraTocPtr = _PrintExtraToc; + + AH->StartBlobsPtr = _StartBlobs; + AH->StartBlobPtr = _StartBlob; + AH->EndBlobPtr = _EndBlob; + AH->EndBlobsPtr = _EndBlobs; + AH->ClonePtr = NULL; + AH->DeClonePtr = NULL; + + AH->WorkerJobDumpPtr = NULL; + AH->WorkerJobRestorePtr = NULL; + + /* + * Set up some special context used in compressing data. + */ + ctx = (lclContext *) pg_malloc0(sizeof(lclContext)); + AH->formatData = (void *) ctx; + ctx->filePos = 0; + ctx->isSpecialScript = 0; + + /* Initialize LO buffering */ + AH->lo_buf_size = LOBBUFSIZE; + AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE); + + /* + * Now open the tar file, and load the TOC if we're in read mode. + */ + if (AH->mode == archModeWrite) + { + if (AH->fSpec && strcmp(AH->fSpec, "") != 0) + { + ctx->tarFH = fopen(AH->fSpec, PG_BINARY_W); + if (ctx->tarFH == NULL) + fatal("could not open TOC file \"%s\" for output: %m", + AH->fSpec); + } + else + { + ctx->tarFH = stdout; + if (ctx->tarFH == NULL) + fatal("could not open TOC file for output: %m"); + } + + ctx->tarFHpos = 0; + + /* + * Make unbuffered since we will dup() it, and the buffers screw each + * other + */ + /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */ + + ctx->hasSeek = checkSeek(ctx->tarFH); + + /* + * We don't support compression because reading the files back is not + * possible since gzdopen uses buffered IO which totally screws file + * positioning. + */ + if (AH->compression != 0) + fatal("compression is not supported by tar archive format"); + } + else + { /* Read Mode */ + if (AH->fSpec && strcmp(AH->fSpec, "") != 0) + { + ctx->tarFH = fopen(AH->fSpec, PG_BINARY_R); + if (ctx->tarFH == NULL) + fatal("could not open TOC file \"%s\" for input: %m", + AH->fSpec); + } + else + { + ctx->tarFH = stdin; + if (ctx->tarFH == NULL) + fatal("could not open TOC file for input: %m"); + } + + /* + * Make unbuffered since we will dup() it, and the buffers screw each + * other + */ + /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */ + + ctx->tarFHpos = 0; + + ctx->hasSeek = checkSeek(ctx->tarFH); + + ctx->FH = (void *) tarOpen(AH, "toc.dat", 'r'); + ReadHead(AH); + ReadToc(AH); + tarClose(AH, ctx->FH); /* Nothing else in the file... */ + } +} + +/* + * - Start a new TOC entry + * Setup the output file name. + */ +static void +_ArchiveEntry(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx; + char fn[K_STD_BUF_SIZE]; + + ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + if (te->dataDumper != NULL) + { +#ifdef HAVE_LIBZ + if (AH->compression == 0) + sprintf(fn, "%d.dat", te->dumpId); + else + sprintf(fn, "%d.dat.gz", te->dumpId); +#else + sprintf(fn, "%d.dat", te->dumpId); +#endif + ctx->filename = pg_strdup(fn); + } + else + { + ctx->filename = NULL; + ctx->TH = NULL; + } + te->formatData = (void *) ctx; +} + +static void +_WriteExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + if (ctx->filename) + WriteStr(AH, ctx->filename); + else + WriteStr(AH, ""); +} + +static void +_ReadExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + if (ctx == NULL) + { + ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); + te->formatData = (void *) ctx; + } + + ctx->filename = ReadStr(AH); + if (strlen(ctx->filename) == 0) + { + free(ctx->filename); + ctx->filename = NULL; + } + ctx->TH = NULL; +} + +static void +_PrintExtraToc(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *ctx = (lclTocEntry *) te->formatData; + + if (AH->public.verbose && ctx->filename != NULL) + ahprintf(AH, "-- File: %s\n", ctx->filename); +} + +static void +_StartData(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + tctx->TH = tarOpen(AH, tctx->filename, 'w'); +} + +static TAR_MEMBER * +tarOpen(ArchiveHandle *AH, const char *filename, char mode) +{ + lclContext *ctx = (lclContext *) AH->formatData; + TAR_MEMBER *tm; + +#ifdef HAVE_LIBZ + char fmode[14]; +#endif + + if (mode == 'r') + { + tm = _tarPositionTo(AH, filename); + if (!tm) /* Not found */ + { + if (filename) + { + /* + * Couldn't find the requested file. Future: do SEEK(0) and + * retry. + */ + fatal("could not find file \"%s\" in archive", filename); + } + else + { + /* Any file OK, none left, so return NULL */ + return NULL; + } + } + +#ifdef HAVE_LIBZ + + if (AH->compression == 0) + tm->nFH = ctx->tarFH; + else + fatal("compression is not supported by tar archive format"); + /* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */ +#else + tm->nFH = ctx->tarFH; +#endif + } + else + { + int old_umask; + + tm = pg_malloc0(sizeof(TAR_MEMBER)); + + /* + * POSIX does not require, but permits, tmpfile() to restrict file + * permissions. Given an OS crash after we write data, the filesystem + * might retain the data but forget tmpfile()'s unlink(). If so, the + * file mode protects confidentiality of the data written. + */ + old_umask = umask(S_IRWXG | S_IRWXO); + +#ifndef WIN32 + tm->tmpFH = tmpfile(); +#else + + /* + * On WIN32, tmpfile() generates a filename in the root directory, + * which requires administrative permissions on certain systems. Loop + * until we find a unique file name we can create. + */ + while (1) + { + char *name; + int fd; + + name = _tempnam(NULL, "pg_temp_"); + if (name == NULL) + break; + fd = open(name, O_RDWR | O_CREAT | O_EXCL | O_BINARY | + O_TEMPORARY, S_IRUSR | S_IWUSR); + free(name); + + if (fd != -1) /* created a file */ + { + tm->tmpFH = fdopen(fd, "w+b"); + break; + } + else if (errno != EEXIST) /* failure other than file exists */ + break; + } +#endif + + if (tm->tmpFH == NULL) + fatal("could not generate temporary file name: %m"); + + umask(old_umask); + +#ifdef HAVE_LIBZ + + if (AH->compression != 0) + { + sprintf(fmode, "wb%d", AH->compression); + tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode); + if (tm->zFH == NULL) + fatal("could not open temporary file"); + } + else + tm->nFH = tm->tmpFH; +#else + + tm->nFH = tm->tmpFH; +#endif + + tm->AH = AH; + tm->targetFile = pg_strdup(filename); + } + + tm->mode = mode; + tm->tarFH = ctx->tarFH; + + return tm; +} + +static void +tarClose(ArchiveHandle *AH, TAR_MEMBER *th) +{ + /* + * Close the GZ file since we dup'd. This will flush the buffers. + */ + if (AH->compression != 0) + { + errno = 0; /* in case gzclose() doesn't set it */ + if (GZCLOSE(th->zFH) != 0) + fatal("could not close tar member: %m"); + } + + if (th->mode == 'w') + _tarAddFile(AH, th); /* This will close the temp file */ + + /* + * else Nothing to do for normal read since we don't dup() normal file + * handle, and we don't use temp files. + */ + + if (th->targetFile) + free(th->targetFile); + + th->nFH = NULL; + th->zFH = NULL; +} + +#ifdef __NOT_USED__ +static char * +tarGets(char *buf, size_t len, TAR_MEMBER *th) +{ + char *s; + size_t cnt = 0; + char c = ' '; + int eof = 0; + + /* Can't read past logical EOF */ + if (len > (th->fileLen - th->pos)) + len = th->fileLen - th->pos; + + while (cnt < len && c != '\n') + { + if (_tarReadRaw(th->AH, &c, 1, th, NULL) <= 0) + { + eof = 1; + break; + } + buf[cnt++] = c; + } + + if (eof && cnt == 0) + s = NULL; + else + { + buf[cnt++] = '\0'; + s = buf; + } + + if (s) + { + len = strlen(s); + th->pos += len; + } + + return s; +} +#endif + +/* + * Just read bytes from the archive. This is the low level read routine + * that is used for ALL reads on a tar file. + */ +static size_t +_tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh) +{ + lclContext *ctx = (lclContext *) AH->formatData; + size_t avail; + size_t used = 0; + size_t res = 0; + + Assert(th || fh); + + avail = AH->lookaheadLen - AH->lookaheadPos; + if (avail > 0) + { + /* We have some lookahead bytes to use */ + if (avail >= len) /* Just use the lookahead buffer */ + used = len; + else + used = avail; + + /* Copy, and adjust buffer pos */ + memcpy(buf, AH->lookahead + AH->lookaheadPos, used); + AH->lookaheadPos += used; + + /* Adjust required length */ + len -= used; + } + + /* Read the file if len > 0 */ + if (len > 0) + { + if (fh) + { + res = fread(&((char *) buf)[used], 1, len, fh); + if (res != len && !feof(fh)) + READ_ERROR_EXIT(fh); + } + else if (th) + { + if (th->zFH) + { + res = GZREAD(&((char *) buf)[used], 1, len, th->zFH); + if (res != len && !GZEOF(th->zFH)) + { +#ifdef HAVE_LIBZ + int errnum; + const char *errmsg = gzerror(th->zFH, &errnum); + + fatal("could not read from input file: %s", + errnum == Z_ERRNO ? strerror(errno) : errmsg); +#else + fatal("could not read from input file: %s", + strerror(errno)); +#endif + } + } + else + { + res = fread(&((char *) buf)[used], 1, len, th->nFH); + if (res != len && !feof(th->nFH)) + READ_ERROR_EXIT(th->nFH); + } + } + } + + ctx->tarFHpos += res + used; + + return (res + used); +} + +static size_t +tarRead(void *buf, size_t len, TAR_MEMBER *th) +{ + size_t res; + + if (th->pos + len > th->fileLen) + len = th->fileLen - th->pos; + + if (len <= 0) + return 0; + + res = _tarReadRaw(th->AH, buf, len, th, NULL); + + th->pos += res; + + return res; +} + +static size_t +tarWrite(const void *buf, size_t len, TAR_MEMBER *th) +{ + size_t res; + + if (th->zFH != NULL) + res = GZWRITE(buf, 1, len, th->zFH); + else + res = fwrite(buf, 1, len, th->nFH); + + th->pos += res; + return res; +} + +static void +_WriteData(ArchiveHandle *AH, const void *data, size_t dLen) +{ + lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData; + + if (tarWrite(data, dLen, tctx->TH) != dLen) + WRITE_ERROR_EXIT; +} + +static void +_EndData(ArchiveHandle *AH, TocEntry *te) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + /* Close the file */ + tarClose(AH, tctx->TH); + tctx->TH = NULL; +} + +/* + * Print data for a given file + */ +static void +_PrintFileData(ArchiveHandle *AH, char *filename) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char buf[4096]; + size_t cnt; + TAR_MEMBER *th; + + if (!filename) + return; + + th = tarOpen(AH, filename, 'r'); + ctx->FH = th; + + while ((cnt = tarRead(buf, 4095, th)) > 0) + { + buf[cnt] = '\0'; + ahwrite(buf, 1, cnt, AH); + } + + tarClose(AH, th); +} + + +/* + * Print data for a given TOC entry +*/ +static void +_PrintTocData(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + int pos1; + + if (!tctx->filename) + return; + + /* + * If we're writing the special restore.sql script, emit a suitable + * command to include each table's data from the corresponding file. + * + * In the COPY case this is a bit klugy because the regular COPY command + * was already printed before we get control. + */ + if (ctx->isSpecialScript) + { + if (te->copyStmt) + { + /* Abort the COPY FROM stdin */ + ahprintf(AH, "\\.\n"); + + /* + * The COPY statement should look like "COPY ... FROM stdin;\n", + * see dumpTableData(). + */ + pos1 = (int) strlen(te->copyStmt) - 13; + if (pos1 < 6 || strncmp(te->copyStmt, "COPY ", 5) != 0 || + strcmp(te->copyStmt + pos1, " FROM stdin;\n") != 0) + fatal("unexpected COPY statement syntax: \"%s\"", + te->copyStmt); + + /* Emit all but the FROM part ... */ + ahwrite(te->copyStmt, 1, pos1, AH); + /* ... and insert modified FROM */ + ahprintf(AH, " FROM '$$PATH$$/%s';\n\n", tctx->filename); + } + else + { + /* --inserts mode, no worries, just include the data file */ + ahprintf(AH, "\\i $$PATH$$/%s\n\n", tctx->filename); + } + + return; + } + + if (strcmp(te->desc, "BLOBS") == 0) + _LoadBlobs(AH); + else + _PrintFileData(AH, tctx->filename); +} + +static void +_LoadBlobs(ArchiveHandle *AH) +{ + Oid oid; + lclContext *ctx = (lclContext *) AH->formatData; + TAR_MEMBER *th; + size_t cnt; + bool foundBlob = false; + char buf[4096]; + + StartRestoreBlobs(AH); + + th = tarOpen(AH, NULL, 'r'); /* Open next file */ + while (th != NULL) + { + ctx->FH = th; + + if (strncmp(th->targetFile, "blob_", 5) == 0) + { + oid = atooid(&th->targetFile[5]); + if (oid != 0) + { + pg_log_info("restoring large object with OID %u", oid); + + StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema); + + while ((cnt = tarRead(buf, 4095, th)) > 0) + { + buf[cnt] = '\0'; + ahwrite(buf, 1, cnt, AH); + } + EndRestoreBlob(AH, oid); + foundBlob = true; + } + tarClose(AH, th); + } + else + { + tarClose(AH, th); + + /* + * Once we have found the first blob, stop at the first non-blob + * entry (which will be 'blobs.toc'). This coding would eat all + * the rest of the archive if there are no blobs ... but this + * function shouldn't be called at all in that case. + */ + if (foundBlob) + break; + } + + th = tarOpen(AH, NULL, 'r'); + } + EndRestoreBlobs(AH); +} + + +static int +_WriteByte(ArchiveHandle *AH, const int i) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char b = i; /* Avoid endian problems */ + + if (tarWrite(&b, 1, ctx->FH) != 1) + WRITE_ERROR_EXIT; + + ctx->filePos += 1; + return 1; +} + +static int +_ReadByte(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + size_t res; + unsigned char c; + + res = tarRead(&c, 1, ctx->FH); + if (res != 1) + /* We already would have exited for errors on reads, must be EOF */ + fatal("could not read from input file: end of file"); + ctx->filePos += 1; + return c; +} + +static void +_WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + if (tarWrite(buf, len, ctx->FH) != len) + WRITE_ERROR_EXIT; + + ctx->filePos += len; +} + +static void +_ReadBuf(ArchiveHandle *AH, void *buf, size_t len) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + if (tarRead(buf, len, ctx->FH) != len) + /* We already would have exited for errors on reads, must be EOF */ + fatal("could not read from input file: end of file"); + + ctx->filePos += len; +} + +static void +_CloseArchive(ArchiveHandle *AH) +{ + lclContext *ctx = (lclContext *) AH->formatData; + TAR_MEMBER *th; + RestoreOptions *ropt; + RestoreOptions *savRopt; + DumpOptions *savDopt; + int savVerbose, + i; + + if (AH->mode == archModeWrite) + { + /* + * Write the Header & TOC to the archive FIRST + */ + th = tarOpen(AH, "toc.dat", 'w'); + ctx->FH = th; + WriteHead(AH); + WriteToc(AH); + tarClose(AH, th); /* Not needed any more */ + + /* + * Now send the data (tables & blobs) + */ + WriteDataChunks(AH, NULL); + + /* + * Now this format wants to append a script which does a full restore + * if the files have been extracted. + */ + th = tarOpen(AH, "restore.sql", 'w'); + + tarPrintf(th, "--\n" + "-- NOTE:\n" + "--\n" + "-- File paths need to be edited. Search for $$PATH$$ and\n" + "-- replace it with the path to the directory containing\n" + "-- the extracted data files.\n" + "--\n"); + + AH->CustomOutPtr = _scriptOut; + + ctx->isSpecialScript = 1; + ctx->scriptTH = th; + + ropt = NewRestoreOptions(); + memcpy(ropt, AH->public.ropt, sizeof(RestoreOptions)); + ropt->filename = NULL; + ropt->dropSchema = 1; + ropt->compression = 0; + ropt->superuser = NULL; + ropt->suppressDumpWarnings = true; + + savDopt = AH->public.dopt; + savRopt = AH->public.ropt; + + SetArchiveOptions((Archive *) AH, NULL, ropt); + + savVerbose = AH->public.verbose; + AH->public.verbose = 0; + + RestoreArchive((Archive *) AH); + + SetArchiveOptions((Archive *) AH, savDopt, savRopt); + + AH->public.verbose = savVerbose; + + tarClose(AH, th); + + ctx->isSpecialScript = 0; + + /* + * EOF marker for tar files is two blocks of NULLs. + */ + for (i = 0; i < TAR_BLOCK_SIZE * 2; i++) + { + if (fputc(0, ctx->tarFH) == EOF) + WRITE_ERROR_EXIT; + } + + /* Sync the output file if one is defined */ + if (AH->dosync && AH->fSpec) + (void) fsync_fname(AH->fSpec, false); + } + + AH->FH = NULL; +} + +static size_t +_scriptOut(ArchiveHandle *AH, const void *buf, size_t len) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + return tarWrite(buf, len, ctx->scriptTH); +} + +/* + * BLOB support + */ + +/* + * Called by the archiver when starting to save all BLOB DATA (not schema). + * This routine should save whatever format-specific information is needed + * to read the BLOBs back into memory. + * + * It is called just prior to the dumper's DataDumper routine. + * + * Optional, but strongly recommended. + * + */ +static void +_StartBlobs(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char fname[K_STD_BUF_SIZE]; + + sprintf(fname, "blobs.toc"); + ctx->blobToc = tarOpen(AH, fname, 'w'); +} + +/* + * Called by the archiver when the dumper calls StartBlob. + * + * Mandatory. + * + * Must save the passed OID for retrieval at restore-time. + */ +static void +_StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclContext *ctx = (lclContext *) AH->formatData; + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + char fname[255]; + char *sfx; + + if (oid == 0) + fatal("invalid OID for large object (%u)", oid); + + if (AH->compression != 0) + sfx = ".gz"; + else + sfx = ""; + + sprintf(fname, "blob_%u.dat%s", oid, sfx); + + tarPrintf(ctx->blobToc, "%u %s\n", oid, fname); + + tctx->TH = tarOpen(AH, fname, 'w'); +} + +/* + * Called by the archiver when the dumper calls EndBlob. + * + * Optional. + * + */ +static void +_EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) +{ + lclTocEntry *tctx = (lclTocEntry *) te->formatData; + + tarClose(AH, tctx->TH); +} + +/* + * Called by the archiver when finishing saving all BLOB DATA. + * + * Optional. + * + */ +static void +_EndBlobs(ArchiveHandle *AH, TocEntry *te) +{ + lclContext *ctx = (lclContext *) AH->formatData; + + /* Write out a fake zero OID to mark end-of-blobs. */ + /* WriteInt(AH, 0); */ + + tarClose(AH, ctx->blobToc); +} + + + +/*------------ + * TAR Support + *------------ + */ + +static int +tarPrintf(TAR_MEMBER *th, const char *fmt,...) +{ + int save_errno = errno; + char *p; + size_t len = 128; /* initial assumption about buffer size */ + size_t cnt; + + for (;;) + { + va_list args; + + /* Allocate work buffer. */ + p = (char *) pg_malloc(len); + + /* Try to format the data. */ + errno = save_errno; + va_start(args, fmt); + cnt = pvsnprintf(p, len, fmt, args); + va_end(args); + + if (cnt < len) + break; /* success */ + + /* Release buffer and loop around to try again with larger len. */ + free(p); + len = cnt; + } + + cnt = tarWrite(p, cnt, th); + free(p); + return (int) cnt; +} + +bool +isValidTarHeader(char *header) +{ + int sum; + int chk = tarChecksum(header); + + sum = read_tar_number(&header[148], 8); + + if (sum != chk) + return false; + + /* POSIX tar format */ + if (memcmp(&header[257], "ustar\0", 6) == 0 && + memcmp(&header[263], "00", 2) == 0) + return true; + /* GNU tar format */ + if (memcmp(&header[257], "ustar \0", 8) == 0) + return true; + /* not-quite-POSIX format written by pre-9.3 pg_dump */ + if (memcmp(&header[257], "ustar00\0", 8) == 0) + return true; + + return false; +} + +/* Given the member, write the TAR header & copy the file */ +static void +_tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th) +{ + lclContext *ctx = (lclContext *) AH->formatData; + FILE *tmp = th->tmpFH; /* Grab it for convenience */ + char buf[32768]; + size_t cnt; + pgoff_t len = 0; + size_t res; + size_t i, + pad; + + /* + * Find file len & go back to start. + */ + if (fseeko(tmp, 0, SEEK_END) != 0) + fatal("error during file seek: %m"); + th->fileLen = ftello(tmp); + if (th->fileLen < 0) + fatal("could not determine seek position in archive file: %m"); + if (fseeko(tmp, 0, SEEK_SET) != 0) + fatal("error during file seek: %m"); + + _tarWriteHeader(th); + + while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0) + { + if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt) + WRITE_ERROR_EXIT; + len += res; + } + if (!feof(tmp)) + READ_ERROR_EXIT(tmp); + + if (fclose(tmp) != 0) /* This *should* delete it... */ + fatal("could not close temporary file: %m"); + + if (len != th->fileLen) + { + char buf1[32], + buf2[32]; + + snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len); + snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen); + fatal("actual file length (%s) does not match expected (%s)", + buf1, buf2); + } + + pad = tarPaddingBytesRequired(len); + for (i = 0; i < pad; i++) + { + if (fputc('\0', th->tarFH) == EOF) + WRITE_ERROR_EXIT; + } + + ctx->tarFHpos += len + pad; +} + +/* Locate the file in the archive, read header and position to data */ +static TAR_MEMBER * +_tarPositionTo(ArchiveHandle *AH, const char *filename) +{ + lclContext *ctx = (lclContext *) AH->formatData; + TAR_MEMBER *th = pg_malloc0(sizeof(TAR_MEMBER)); + char c; + char header[TAR_BLOCK_SIZE]; + size_t i, + len, + blks; + int id; + + th->AH = AH; + + /* Go to end of current file, if any */ + if (ctx->tarFHpos != 0) + { + char buf1[100], + buf2[100]; + + snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ctx->tarFHpos); + snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ctx->tarNextMember); + pg_log_debug("moving from position %s to next member at file position %s", + buf1, buf2); + + while (ctx->tarFHpos < ctx->tarNextMember) + _tarReadRaw(AH, &c, 1, NULL, ctx->tarFH); + } + + { + char buf[100]; + + snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ctx->tarFHpos); + pg_log_debug("now at file position %s", buf); + } + + /* We are at the start of the file, or at the next member */ + + /* Get the header */ + if (!_tarGetHeader(AH, th)) + { + if (filename) + fatal("could not find header for file \"%s\" in tar archive", filename); + else + { + /* + * We're just scanning the archive for the next file, so return + * null + */ + free(th); + return NULL; + } + } + + while (filename != NULL && strcmp(th->targetFile, filename) != 0) + { + pg_log_debug("skipping tar member %s", th->targetFile); + + id = atoi(th->targetFile); + if ((TocIDRequired(AH, id) & REQ_DATA) != 0) + fatal("restoring data out of order is not supported in this archive format: " + "\"%s\" is required, but comes before \"%s\" in the archive file.", + th->targetFile, filename); + + /* Header doesn't match, so read to next header */ + len = th->fileLen; + len += tarPaddingBytesRequired(th->fileLen); + blks = len / TAR_BLOCK_SIZE; /* # of tar blocks */ + + for (i = 0; i < blks; i++) + _tarReadRaw(AH, &header[0], TAR_BLOCK_SIZE, NULL, ctx->tarFH); + + if (!_tarGetHeader(AH, th)) + fatal("could not find header for file \"%s\" in tar archive", filename); + } + + ctx->tarNextMember = ctx->tarFHpos + th->fileLen + + tarPaddingBytesRequired(th->fileLen); + th->pos = 0; + + return th; +} + +/* Read & verify a header */ +static int +_tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th) +{ + lclContext *ctx = (lclContext *) AH->formatData; + char h[TAR_BLOCK_SIZE]; + char tag[100 + 1]; + int sum, + chk; + pgoff_t len; + pgoff_t hPos; + bool gotBlock = false; + + while (!gotBlock) + { + /* Save the pos for reporting purposes */ + hPos = ctx->tarFHpos; + + /* Read the next tar block, return EOF, exit if short */ + len = _tarReadRaw(AH, h, TAR_BLOCK_SIZE, NULL, ctx->tarFH); + if (len == 0) /* EOF */ + return 0; + + if (len != TAR_BLOCK_SIZE) + fatal(ngettext("incomplete tar header found (%lu byte)", + "incomplete tar header found (%lu bytes)", + len), + (unsigned long) len); + + /* Calc checksum */ + chk = tarChecksum(h); + sum = read_tar_number(&h[148], 8); + + /* + * If the checksum failed, see if it is a null block. If so, silently + * continue to the next block. + */ + if (chk == sum) + gotBlock = true; + else + { + int i; + + for (i = 0; i < TAR_BLOCK_SIZE; i++) + { + if (h[i] != 0) + { + gotBlock = true; + break; + } + } + } + } + + /* Name field is 100 bytes, might not be null-terminated */ + strlcpy(tag, &h[0], 100 + 1); + + len = read_tar_number(&h[124], 12); + + { + char posbuf[32]; + char lenbuf[32]; + + snprintf(posbuf, sizeof(posbuf), UINT64_FORMAT, (uint64) hPos); + snprintf(lenbuf, sizeof(lenbuf), UINT64_FORMAT, (uint64) len); + pg_log_debug("TOC Entry %s at %s (length %s, checksum %d)", + tag, posbuf, lenbuf, sum); + } + + if (chk != sum) + { + char posbuf[32]; + + snprintf(posbuf, sizeof(posbuf), UINT64_FORMAT, + (uint64) ftello(ctx->tarFH)); + fatal("corrupt tar header found in %s (expected %d, computed %d) file position %s", + tag, sum, chk, posbuf); + } + + th->targetFile = pg_strdup(tag); + th->fileLen = len; + + return 1; +} + + +static void +_tarWriteHeader(TAR_MEMBER *th) +{ + char h[TAR_BLOCK_SIZE]; + + tarCreateHeader(h, th->targetFile, NULL, th->fileLen, + 0600, 04000, 02000, time(NULL)); + + /* Now write the completed header. */ + if (fwrite(h, 1, TAR_BLOCK_SIZE, th->tarFH) != TAR_BLOCK_SIZE) + WRITE_ERROR_EXIT; +} diff --git a/src/bin/pg_dump/pg_backup_tar.h b/src/bin/pg_dump/pg_backup_tar.h new file mode 100644 index 0000000..0277f08 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_tar.h @@ -0,0 +1,37 @@ +/* + * src/bin/pg_dump/pg_backup_tar.h + * + * TAR Header (see "ustar interchange format" in POSIX 1003.1) + * + * Offset Length Contents + * 0 100 bytes File name ('\0' terminated, 99 maximum length) + * 100 8 bytes File mode (in octal ascii) + * 108 8 bytes User ID (in octal ascii) + * 116 8 bytes Group ID (in octal ascii) + * 124 12 bytes File size (in octal ascii) + * 136 12 bytes Modify time (Unix timestamp in octal ascii) + * 148 8 bytes Header checksum (in octal ascii) + * 156 1 bytes Type flag (see below) + * 157 100 bytes Linkname, if symlink ('\0' terminated, 99 maximum length) + * 257 6 bytes Magic ("ustar\0") + * 263 2 bytes Version ("00") + * 265 32 bytes User name ('\0' terminated, 31 maximum length) + * 297 32 bytes Group name ('\0' terminated, 31 maximum length) + * 329 8 bytes Major device ID (in octal ascii) + * 337 8 bytes Minor device ID (in octal ascii) + * 345 155 bytes File name prefix (not used in our implementation) + * 500 12 bytes Padding + * + * 512 (s+p)bytes File contents, padded out to 512-byte boundary + */ + +/* The type flag defines the type of file */ +#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */ +#define LF_NORMAL '0' /* Normal disk file */ +#define LF_LINK '1' /* Link to previously dumped file */ +#define LF_SYMLINK '2' /* Symbolic link */ +#define LF_CHR '3' /* Character special file */ +#define LF_BLK '4' /* Block special file */ +#define LF_DIR '5' /* Directory */ +#define LF_FIFO '6' /* FIFO special file */ +#define LF_CONTIG '7' /* Contiguous file */ diff --git a/src/bin/pg_dump/pg_backup_utils.c b/src/bin/pg_dump/pg_backup_utils.c new file mode 100644 index 0000000..c709a40 --- /dev/null +++ b/src/bin/pg_dump/pg_backup_utils.c @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_utils.c + * Utility routines shared by pg_dump and pg_restore + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/pg_backup_utils.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "parallel.h" +#include "pg_backup_utils.h" + +/* Globals exported by this file */ +const char *progname = NULL; + +#define MAX_ON_EXIT_NICELY 20 + +static struct +{ + on_exit_nicely_callback function; + void *arg; +} on_exit_nicely_list[MAX_ON_EXIT_NICELY]; + +static int on_exit_nicely_index; + +/* + * Parse a --section=foo command line argument. + * + * Set or update the bitmask in *dumpSections according to arg. + * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and + * pg_restore so they can know if this has even been called. + */ +void +set_dump_section(const char *arg, int *dumpSections) +{ + /* if this is the first call, clear all the bits */ + if (*dumpSections == DUMP_UNSECTIONED) + *dumpSections = 0; + + if (strcmp(arg, "pre-data") == 0) + *dumpSections |= DUMP_PRE_DATA; + else if (strcmp(arg, "data") == 0) + *dumpSections |= DUMP_DATA; + else if (strcmp(arg, "post-data") == 0) + *dumpSections |= DUMP_POST_DATA; + else + { + pg_log_error("unrecognized section name: \"%s\"", arg); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } +} + + +/* Register a callback to be run when exit_nicely is invoked. */ +void +on_exit_nicely(on_exit_nicely_callback function, void *arg) +{ + if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY) + { + pg_log_fatal("out of on_exit_nicely slots"); + exit_nicely(1); + } + on_exit_nicely_list[on_exit_nicely_index].function = function; + on_exit_nicely_list[on_exit_nicely_index].arg = arg; + on_exit_nicely_index++; +} + +/* + * Run accumulated on_exit_nicely callbacks in reverse order and then exit + * without printing any message. + * + * If running in a parallel worker thread on Windows, we only exit the thread, + * not the whole process. + * + * Note that in parallel operation on Windows, the callback(s) will be run + * by each thread since the list state is necessarily shared by all threads; + * each callback must contain logic to ensure it does only what's appropriate + * for its thread. On Unix, callbacks are also run by each process, but only + * for callbacks established before we fork off the child processes. (It'd + * be cleaner to reset the list after fork(), and let each child establish + * its own callbacks; but then the behavior would be completely inconsistent + * between Windows and Unix. For now, just be sure to establish callbacks + * before forking to avoid inconsistency.) + */ +void +exit_nicely(int code) +{ + int i; + + for (i = on_exit_nicely_index - 1; i >= 0; i--) + on_exit_nicely_list[i].function(code, + on_exit_nicely_list[i].arg); + +#ifdef WIN32 + if (parallel_init_done && GetCurrentThreadId() != mainThreadId) + _endthreadex(code); +#endif + + exit(code); +} diff --git a/src/bin/pg_dump/pg_backup_utils.h b/src/bin/pg_dump/pg_backup_utils.h new file mode 100644 index 0000000..306798f --- /dev/null +++ b/src/bin/pg_dump/pg_backup_utils.h @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------- + * + * pg_backup_utils.h + * Utility routines shared by pg_dump and pg_restore. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/pg_backup_utils.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_BACKUP_UTILS_H +#define PG_BACKUP_UTILS_H + +#include "common/logging.h" + +/* bits returned by set_dump_section */ +#define DUMP_PRE_DATA 0x01 +#define DUMP_DATA 0x02 +#define DUMP_POST_DATA 0x04 +#define DUMP_UNSECTIONED 0xff + +typedef void (*on_exit_nicely_callback) (int code, void *arg); + +extern const char *progname; + +extern void set_dump_section(const char *arg, int *dumpSections); +extern void on_exit_nicely(on_exit_nicely_callback function, void *arg); +extern void exit_nicely(int code) pg_attribute_noreturn(); + +#define fatal(...) do { pg_log_error(__VA_ARGS__); exit_nicely(1); } while(0) + +#endif /* PG_BACKUP_UTILS_H */ diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c new file mode 100644 index 0000000..e110257 --- /dev/null +++ b/src/bin/pg_dump/pg_dump.c @@ -0,0 +1,18953 @@ +/*------------------------------------------------------------------------- + * + * pg_dump.c + * pg_dump is a utility for dumping out a postgres database + * into a script file. + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * pg_dump will read the system catalogs in a database and dump out a + * script that reproduces the schema in terms of SQL that is understood + * by PostgreSQL + * + * Note that pg_dump runs in a transaction-snapshot mode transaction, + * so it sees a consistent snapshot of the database including system + * catalogs. However, it relies in part on various specialized backend + * functions like pg_get_indexdef(), and those things tend to look at + * the currently committed state. So it is possible to get 'cache + * lookup failed' error if someone performs DDL changes while a dump is + * happening. The window for this sort of thing is from the acquisition + * of the transaction snapshot to getSchemaData() (when pg_dump acquires + * AccessShareLock on every table it intends to dump). It isn't very large, + * but it can happen. + * + * http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php + * + * IDENTIFICATION + * src/bin/pg_dump/pg_dump.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#include +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#include "access/attnum.h" +#include "access/sysattr.h" +#include "access/transam.h" +#include "catalog/pg_aggregate_d.h" +#include "catalog/pg_am_d.h" +#include "catalog/pg_attribute_d.h" +#include "catalog/pg_cast_d.h" +#include "catalog/pg_class_d.h" +#include "catalog/pg_default_acl_d.h" +#include "catalog/pg_largeobject_d.h" +#include "catalog/pg_largeobject_metadata_d.h" +#include "catalog/pg_proc_d.h" +#include "catalog/pg_trigger_d.h" +#include "catalog/pg_type_d.h" +#include "common/connect.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" +#include "getopt_long.h" +#include "libpq/libpq-fs.h" +#include "parallel.h" +#include "pg_backup_db.h" +#include "pg_backup_utils.h" +#include "pg_dump.h" +#include "storage/block.h" + +typedef struct +{ + const char *descr; /* comment for an object */ + Oid classoid; /* object class (catalog OID) */ + Oid objoid; /* object OID */ + int objsubid; /* subobject (table column #) */ +} CommentItem; + +typedef struct +{ + const char *provider; /* label provider of this security label */ + const char *label; /* security label for an object */ + Oid classoid; /* object class (catalog OID) */ + Oid objoid; /* object OID */ + int objsubid; /* subobject (table column #) */ +} SecLabelItem; + +typedef enum OidOptions +{ + zeroIsError = 1, + zeroAsStar = 2, + zeroAsNone = 4 +} OidOptions; + +/* global decls */ +static bool dosync = true; /* Issue fsync() to make dump durable on disk. */ + +/* subquery used to convert user ID (eg, datdba) to user name */ +static const char *username_subquery; + +/* + * For 8.0 and earlier servers, pulled from pg_database, for 8.1+ we use + * FirstNormalObjectId - 1. + */ +static Oid g_last_builtin_oid; /* value of the last builtin oid */ + +/* The specified names/patterns should to match at least one entity */ +static int strict_names = 0; + +/* + * Object inclusion/exclusion lists + * + * The string lists record the patterns given by command-line switches, + * which we then convert to lists of OIDs of matching objects. + */ +static SimpleStringList schema_include_patterns = {NULL, NULL}; +static SimpleOidList schema_include_oids = {NULL, NULL}; +static SimpleStringList schema_exclude_patterns = {NULL, NULL}; +static SimpleOidList schema_exclude_oids = {NULL, NULL}; + +static SimpleStringList table_include_patterns = {NULL, NULL}; +static SimpleOidList table_include_oids = {NULL, NULL}; +static SimpleStringList table_exclude_patterns = {NULL, NULL}; +static SimpleOidList table_exclude_oids = {NULL, NULL}; +static SimpleStringList tabledata_exclude_patterns = {NULL, NULL}; +static SimpleOidList tabledata_exclude_oids = {NULL, NULL}; +static SimpleStringList foreign_servers_include_patterns = {NULL, NULL}; +static SimpleOidList foreign_servers_include_oids = {NULL, NULL}; + +static SimpleStringList extension_include_patterns = {NULL, NULL}; +static SimpleOidList extension_include_oids = {NULL, NULL}; + +static const CatalogId nilCatalogId = {0, 0}; + +/* override for standard extra_float_digits setting */ +static bool have_extra_float_digits = false; +static int extra_float_digits; + +/* + * The default number of rows per INSERT when + * --inserts is specified without --rows-per-insert + */ +#define DUMP_DEFAULT_ROWS_PER_INSERT 1 + +/* + * Macro for producing quoted, schema-qualified name of a dumpable object. + */ +#define fmtQualifiedDumpable(obj) \ + fmtQualifiedId((obj)->dobj.namespace->dobj.name, \ + (obj)->dobj.name) + +static void help(const char *progname); +static void setup_connection(Archive *AH, + const char *dumpencoding, const char *dumpsnapshot, + char *use_role); +static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode); +static void expand_schema_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names); +static void expand_extension_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names); +static void expand_foreign_server_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids); +static void expand_table_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names); +static void prohibit_crossdb_refs(PGconn *conn, const char *dbname, + const char *pattern); + +static NamespaceInfo *findNamespace(Oid nsoid); +static void dumpTableData(Archive *fout, const TableDataInfo *tdinfo); +static void refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo); +static void guessConstraintInheritance(TableInfo *tblinfo, int numTables); +static void dumpComment(Archive *fout, const char *type, const char *name, + const char *namespace, const char *owner, + CatalogId catalogId, int subid, DumpId dumpId); +static int findComments(Archive *fout, Oid classoid, Oid objoid, + CommentItem **items); +static int collectComments(Archive *fout, CommentItem **items); +static void dumpSecLabel(Archive *fout, const char *type, const char *name, + const char *namespace, const char *owner, + CatalogId catalogId, int subid, DumpId dumpId); +static int findSecLabels(Archive *fout, Oid classoid, Oid objoid, + SecLabelItem **items); +static int collectSecLabels(Archive *fout, SecLabelItem **items); +static void dumpDumpableObject(Archive *fout, const DumpableObject *dobj); +static void dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo); +static void dumpExtension(Archive *fout, const ExtensionInfo *extinfo); +static void dumpType(Archive *fout, const TypeInfo *tyinfo); +static void dumpBaseType(Archive *fout, const TypeInfo *tyinfo); +static void dumpEnumType(Archive *fout, const TypeInfo *tyinfo); +static void dumpRangeType(Archive *fout, const TypeInfo *tyinfo); +static void dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo); +static void dumpDomain(Archive *fout, const TypeInfo *tyinfo); +static void dumpCompositeType(Archive *fout, const TypeInfo *tyinfo); +static void dumpCompositeTypeColComments(Archive *fout, const TypeInfo *tyinfo); +static void dumpShellType(Archive *fout, const ShellTypeInfo *stinfo); +static void dumpProcLang(Archive *fout, const ProcLangInfo *plang); +static void dumpFunc(Archive *fout, const FuncInfo *finfo); +static void dumpCast(Archive *fout, const CastInfo *cast); +static void dumpTransform(Archive *fout, const TransformInfo *transform); +static void dumpOpr(Archive *fout, const OprInfo *oprinfo); +static void dumpAccessMethod(Archive *fout, const AccessMethodInfo *oprinfo); +static void dumpOpclass(Archive *fout, const OpclassInfo *opcinfo); +static void dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo); +static void dumpCollation(Archive *fout, const CollInfo *collinfo); +static void dumpConversion(Archive *fout, const ConvInfo *convinfo); +static void dumpRule(Archive *fout, const RuleInfo *rinfo); +static void dumpAgg(Archive *fout, const AggInfo *agginfo); +static void dumpTrigger(Archive *fout, const TriggerInfo *tginfo); +static void dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo); +static void dumpTable(Archive *fout, const TableInfo *tbinfo); +static void dumpTableSchema(Archive *fout, const TableInfo *tbinfo); +static void dumpTableAttach(Archive *fout, const TableAttachInfo *tbinfo); +static void dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo); +static void dumpSequence(Archive *fout, const TableInfo *tbinfo); +static void dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo); +static void dumpIndex(Archive *fout, const IndxInfo *indxinfo); +static void dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo); +static void dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo); +static void dumpConstraint(Archive *fout, const ConstraintInfo *coninfo); +static void dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo); +static void dumpTSParser(Archive *fout, const TSParserInfo *prsinfo); +static void dumpTSDictionary(Archive *fout, const TSDictInfo *dictinfo); +static void dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo); +static void dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo); +static void dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo); +static void dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo); +static void dumpUserMappings(Archive *fout, + const char *servername, const char *namespace, + const char *owner, CatalogId catalogId, DumpId dumpId); +static void dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo); + +static DumpId dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId, + const char *type, const char *name, const char *subname, + const char *nspname, const char *owner, + const char *acls, const char *racls, + const char *initacls, const char *initracls); + +static void getDependencies(Archive *fout); +static void BuildArchiveDependencies(Archive *fout); +static void findDumpableDependencies(ArchiveHandle *AH, const DumpableObject *dobj, + DumpId **dependencies, int *nDeps, int *allocDeps); + +static DumpableObject *createBoundaryObjects(void); +static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs, + DumpableObject *boundaryObjs); + +static void addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx); +static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo); +static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind); +static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo); +static void buildMatViewRefreshDependencies(Archive *fout); +static void getTableDataFKConstraints(void); +static char *format_function_arguments(const FuncInfo *finfo, const char *funcargs, + bool is_agg); +static char *format_function_arguments_old(Archive *fout, + const FuncInfo *finfo, int nallargs, + char **allargtypes, + char **argmodes, + char **argnames); +static char *format_function_signature(Archive *fout, + const FuncInfo *finfo, bool honor_quotes); +static char *convertRegProcReference(const char *proc); +static char *getFormattedOperatorName(const char *oproid); +static char *convertTSFunction(Archive *fout, Oid funcOid); +static Oid findLastBuiltinOid_V71(Archive *fout); +static const char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts); +static void getBlobs(Archive *fout); +static void dumpBlob(Archive *fout, const BlobInfo *binfo); +static int dumpBlobs(Archive *fout, const void *arg); +static void dumpPolicy(Archive *fout, const PolicyInfo *polinfo); +static void dumpPublication(Archive *fout, const PublicationInfo *pubinfo); +static void dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo); +static void dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo); +static void dumpDatabase(Archive *AH); +static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf, + const char *dbname, Oid dboid); +static void dumpEncoding(Archive *AH); +static void dumpStdStrings(Archive *AH); +static void dumpSearchPath(Archive *AH); +static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout, + PQExpBuffer upgrade_buffer, + Oid pg_type_oid, + bool force_array_type, + bool include_multirange_type); +static void binary_upgrade_set_type_oids_by_rel_oid(Archive *fout, + PQExpBuffer upgrade_buffer, Oid pg_rel_oid); +static void binary_upgrade_set_pg_class_oids(Archive *fout, + PQExpBuffer upgrade_buffer, + Oid pg_class_oid, bool is_index); +static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer, + const DumpableObject *dobj, + const char *objtype, + const char *objname, + const char *objnamespace); +static const char *getAttrName(int attrnum, const TableInfo *tblInfo); +static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer); +static bool nonemptyReloptions(const char *reloptions); +static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions, + const char *prefix, Archive *fout); +static char *get_synchronized_snapshot(Archive *fout); +static void setupDumpWorker(Archive *AHX); +static TableInfo *getRootTableInfo(const TableInfo *tbinfo); + + +int +main(int argc, char **argv) +{ + int c; + const char *filename = NULL; + const char *format = "p"; + TableInfo *tblinfo; + int numTables; + DumpableObject **dobjs; + int numObjs; + DumpableObject *boundaryObjs; + int i; + int optindex; + char *endptr; + RestoreOptions *ropt; + Archive *fout; /* the script file */ + bool g_verbose = false; + const char *dumpencoding = NULL; + const char *dumpsnapshot = NULL; + char *use_role = NULL; + long rowsPerInsert; + int numWorkers = 1; + int compressLevel = -1; + int plainText = 0; + ArchiveFormat archiveFormat = archUnknown; + ArchiveMode archiveMode; + + static DumpOptions dopt; + + static struct option long_options[] = { + {"data-only", no_argument, NULL, 'a'}, + {"blobs", no_argument, NULL, 'b'}, + {"no-blobs", no_argument, NULL, 'B'}, + {"clean", no_argument, NULL, 'c'}, + {"create", no_argument, NULL, 'C'}, + {"dbname", required_argument, NULL, 'd'}, + {"extension", required_argument, NULL, 'e'}, + {"file", required_argument, NULL, 'f'}, + {"format", required_argument, NULL, 'F'}, + {"host", required_argument, NULL, 'h'}, + {"jobs", 1, NULL, 'j'}, + {"no-reconnect", no_argument, NULL, 'R'}, + {"no-owner", no_argument, NULL, 'O'}, + {"port", required_argument, NULL, 'p'}, + {"schema", required_argument, NULL, 'n'}, + {"exclude-schema", required_argument, NULL, 'N'}, + {"schema-only", no_argument, NULL, 's'}, + {"superuser", required_argument, NULL, 'S'}, + {"table", required_argument, NULL, 't'}, + {"exclude-table", required_argument, NULL, 'T'}, + {"no-password", no_argument, NULL, 'w'}, + {"password", no_argument, NULL, 'W'}, + {"username", required_argument, NULL, 'U'}, + {"verbose", no_argument, NULL, 'v'}, + {"no-privileges", no_argument, NULL, 'x'}, + {"no-acl", no_argument, NULL, 'x'}, + {"compress", required_argument, NULL, 'Z'}, + {"encoding", required_argument, NULL, 'E'}, + {"help", no_argument, NULL, '?'}, + {"version", no_argument, NULL, 'V'}, + + /* + * the following options don't have an equivalent short option letter + */ + {"attribute-inserts", no_argument, &dopt.column_inserts, 1}, + {"binary-upgrade", no_argument, &dopt.binary_upgrade, 1}, + {"column-inserts", no_argument, &dopt.column_inserts, 1}, + {"disable-dollar-quoting", no_argument, &dopt.disable_dollar_quoting, 1}, + {"disable-triggers", no_argument, &dopt.disable_triggers, 1}, + {"enable-row-security", no_argument, &dopt.enable_row_security, 1}, + {"exclude-table-data", required_argument, NULL, 4}, + {"extra-float-digits", required_argument, NULL, 8}, + {"if-exists", no_argument, &dopt.if_exists, 1}, + {"inserts", no_argument, NULL, 9}, + {"lock-wait-timeout", required_argument, NULL, 2}, + {"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1}, + {"quote-all-identifiers", no_argument, "e_all_identifiers, 1}, + {"load-via-partition-root", no_argument, &dopt.load_via_partition_root, 1}, + {"role", required_argument, NULL, 3}, + {"section", required_argument, NULL, 5}, + {"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1}, + {"snapshot", required_argument, NULL, 6}, + {"strict-names", no_argument, &strict_names, 1}, + {"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1}, + {"no-comments", no_argument, &dopt.no_comments, 1}, + {"no-publications", no_argument, &dopt.no_publications, 1}, + {"no-security-labels", no_argument, &dopt.no_security_labels, 1}, + {"no-subscriptions", no_argument, &dopt.no_subscriptions, 1}, + {"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1}, + {"no-toast-compression", no_argument, &dopt.no_toast_compression, 1}, + {"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1}, + {"no-sync", no_argument, NULL, 7}, + {"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1}, + {"rows-per-insert", required_argument, NULL, 10}, + {"include-foreign-data", required_argument, NULL, 11}, + + {NULL, 0, NULL, 0} + }; + + pg_logging_init(argv[0]); + pg_logging_set_level(PG_LOG_WARNING); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump")); + + /* + * Initialize what we need for parallel execution, especially for thread + * support on Windows. + */ + init_parallel_dump_utils(); + + progname = get_progname(argv[0]); + + if (argc > 1) + { + if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) + { + help(progname); + exit_nicely(0); + } + if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) + { + puts("pg_dump (PostgreSQL) " PG_VERSION); + exit_nicely(0); + } + } + + InitDumpOptions(&dopt); + + while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:", + long_options, &optindex)) != -1) + { + switch (c) + { + case 'a': /* Dump data only */ + dopt.dataOnly = true; + break; + + case 'b': /* Dump blobs */ + dopt.outputBlobs = true; + break; + + case 'B': /* Don't dump blobs */ + dopt.dontOutputBlobs = true; + break; + + case 'c': /* clean (i.e., drop) schema prior to create */ + dopt.outputClean = 1; + break; + + case 'C': /* Create DB */ + dopt.outputCreateDB = 1; + break; + + case 'd': /* database name */ + dopt.cparams.dbname = pg_strdup(optarg); + break; + + case 'e': /* include extension(s) */ + simple_string_list_append(&extension_include_patterns, optarg); + dopt.include_everything = false; + break; + + case 'E': /* Dump encoding */ + dumpencoding = pg_strdup(optarg); + break; + + case 'f': + filename = pg_strdup(optarg); + break; + + case 'F': + format = pg_strdup(optarg); + break; + + case 'h': /* server host */ + dopt.cparams.pghost = pg_strdup(optarg); + break; + + case 'j': /* number of dump jobs */ + numWorkers = atoi(optarg); + break; + + case 'n': /* include schema(s) */ + simple_string_list_append(&schema_include_patterns, optarg); + dopt.include_everything = false; + break; + + case 'N': /* exclude schema(s) */ + simple_string_list_append(&schema_exclude_patterns, optarg); + break; + + case 'O': /* Don't reconnect to match owner */ + dopt.outputNoOwner = 1; + break; + + case 'p': /* server port */ + dopt.cparams.pgport = pg_strdup(optarg); + break; + + case 'R': + /* no-op, still accepted for backwards compatibility */ + break; + + case 's': /* dump schema only */ + dopt.schemaOnly = true; + break; + + case 'S': /* Username for superuser in plain text output */ + dopt.outputSuperuser = pg_strdup(optarg); + break; + + case 't': /* include table(s) */ + simple_string_list_append(&table_include_patterns, optarg); + dopt.include_everything = false; + break; + + case 'T': /* exclude table(s) */ + simple_string_list_append(&table_exclude_patterns, optarg); + break; + + case 'U': + dopt.cparams.username = pg_strdup(optarg); + break; + + case 'v': /* verbose */ + g_verbose = true; + pg_logging_increase_verbosity(); + break; + + case 'w': + dopt.cparams.promptPassword = TRI_NO; + break; + + case 'W': + dopt.cparams.promptPassword = TRI_YES; + break; + + case 'x': /* skip ACL dump */ + dopt.aclsSkip = true; + break; + + case 'Z': /* Compression Level */ + compressLevel = atoi(optarg); + if (compressLevel < 0 || compressLevel > 9) + { + pg_log_error("compression level must be in range 0..9"); + exit_nicely(1); + } + break; + + case 0: + /* This covers the long options. */ + break; + + case 2: /* lock-wait-timeout */ + dopt.lockWaitTimeout = pg_strdup(optarg); + break; + + case 3: /* SET ROLE */ + use_role = pg_strdup(optarg); + break; + + case 4: /* exclude table(s) data */ + simple_string_list_append(&tabledata_exclude_patterns, optarg); + break; + + case 5: /* section */ + set_dump_section(optarg, &dopt.dumpSections); + break; + + case 6: /* snapshot */ + dumpsnapshot = pg_strdup(optarg); + break; + + case 7: /* no-sync */ + dosync = false; + break; + + case 8: + have_extra_float_digits = true; + extra_float_digits = atoi(optarg); + if (extra_float_digits < -15 || extra_float_digits > 3) + { + pg_log_error("extra_float_digits must be in range -15..3"); + exit_nicely(1); + } + break; + + case 9: /* inserts */ + + /* + * dump_inserts also stores --rows-per-insert, careful not to + * overwrite that. + */ + if (dopt.dump_inserts == 0) + dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT; + break; + + case 10: /* rows per insert */ + errno = 0; + rowsPerInsert = strtol(optarg, &endptr, 10); + + if (endptr == optarg || *endptr != '\0' || + rowsPerInsert <= 0 || rowsPerInsert > INT_MAX || + errno == ERANGE) + { + pg_log_error("rows-per-insert must be in range %d..%d", + 1, INT_MAX); + exit_nicely(1); + } + dopt.dump_inserts = (int) rowsPerInsert; + break; + + case 11: /* include foreign data */ + simple_string_list_append(&foreign_servers_include_patterns, + optarg); + break; + + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit_nicely(1); + } + } + + /* + * Non-option argument specifies database name as long as it wasn't + * already specified with -d / --dbname + */ + if (optind < argc && dopt.cparams.dbname == NULL) + dopt.cparams.dbname = argv[optind++]; + + /* Complain if any arguments remain */ + if (optind < argc) + { + pg_log_error("too many command-line arguments (first is \"%s\")", + argv[optind]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + /* --column-inserts implies --inserts */ + if (dopt.column_inserts && dopt.dump_inserts == 0) + dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT; + + /* + * Binary upgrade mode implies dumping sequence data even in schema-only + * mode. This is not exposed as a separate option, but kept separate + * internally for clarity. + */ + if (dopt.binary_upgrade) + dopt.sequence_data = 1; + + if (dopt.dataOnly && dopt.schemaOnly) + { + pg_log_error("options -s/--schema-only and -a/--data-only cannot be used together"); + exit_nicely(1); + } + + if (dopt.schemaOnly && foreign_servers_include_patterns.head != NULL) + fatal("options -s/--schema-only and --include-foreign-data cannot be used together"); + + if (numWorkers > 1 && foreign_servers_include_patterns.head != NULL) + fatal("option --include-foreign-data is not supported with parallel backup"); + + if (dopt.dataOnly && dopt.outputClean) + { + pg_log_error("options -c/--clean and -a/--data-only cannot be used together"); + exit_nicely(1); + } + + if (dopt.if_exists && !dopt.outputClean) + fatal("option --if-exists requires option -c/--clean"); + + /* + * --inserts are already implied above if --column-inserts or + * --rows-per-insert were specified. + */ + if (dopt.do_nothing && dopt.dump_inserts == 0) + fatal("option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts"); + + /* Identify archive format to emit */ + archiveFormat = parseArchiveFormat(format, &archiveMode); + + /* archiveFormat specific setup */ + if (archiveFormat == archNull) + plainText = 1; + + /* Custom and directory formats are compressed by default, others not */ + if (compressLevel == -1) + { +#ifdef HAVE_LIBZ + if (archiveFormat == archCustom || archiveFormat == archDirectory) + compressLevel = Z_DEFAULT_COMPRESSION; + else +#endif + compressLevel = 0; + } + +#ifndef HAVE_LIBZ + if (compressLevel != 0) + pg_log_warning("requested compression not available in this installation -- archive will be uncompressed"); + compressLevel = 0; +#endif + + /* + * If emitting an archive format, we always want to emit a DATABASE item, + * in case --create is specified at pg_restore time. + */ + if (!plainText) + dopt.outputCreateDB = 1; + + /* + * On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually) + * parallel jobs because that's the maximum limit for the + * WaitForMultipleObjects() call. + */ + if (numWorkers <= 0 +#ifdef WIN32 + || numWorkers > MAXIMUM_WAIT_OBJECTS +#endif + ) + fatal("invalid number of parallel jobs"); + + /* Parallel backup only in the directory archive format so far */ + if (archiveFormat != archDirectory && numWorkers > 1) + fatal("parallel backup only supported by the directory format"); + + /* Open the output file */ + fout = CreateArchive(filename, archiveFormat, compressLevel, dosync, + archiveMode, setupDumpWorker); + + /* Make dump options accessible right away */ + SetArchiveOptions(fout, &dopt, NULL); + + /* Register the cleanup hook */ + on_exit_close_archive(fout); + + /* Let the archiver know how noisy to be */ + fout->verbose = g_verbose; + + + /* + * We allow the server to be back to 8.0, and up to any minor release of + * our own major version. (See also version check in pg_dumpall.c.) + */ + fout->minRemoteVersion = 80000; + fout->maxRemoteVersion = (PG_VERSION_NUM / 100) * 100 + 99; + + fout->numWorkers = numWorkers; + + /* + * Open the database using the Archiver, so it knows about it. Errors mean + * death. + */ + ConnectDatabase(fout, &dopt.cparams, false); + setup_connection(fout, dumpencoding, dumpsnapshot, use_role); + + /* + * Disable security label support if server version < v9.1.x (prevents + * access to nonexistent pg_seclabel catalog) + */ + if (fout->remoteVersion < 90100) + dopt.no_security_labels = 1; + + /* + * On hot standbys, never try to dump unlogged table data, since it will + * just throw an error. + */ + if (fout->isStandby) + dopt.no_unlogged_table_data = true; + + /* Select the appropriate subquery to convert user IDs to names */ + if (fout->remoteVersion >= 80100) + username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid ="; + else + username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid ="; + + /* check the version for the synchronized snapshots feature */ + if (numWorkers > 1 && fout->remoteVersion < 90200 + && !dopt.no_synchronized_snapshots) + fatal("Synchronized snapshots are not supported by this server version.\n" + "Run with --no-synchronized-snapshots instead if you do not need\n" + "synchronized snapshots."); + + /* check the version when a snapshot is explicitly specified by user */ + if (dumpsnapshot && fout->remoteVersion < 90200) + fatal("Exported snapshots are not supported by this server version."); + + /* + * Find the last built-in OID, if needed (prior to 8.1) + * + * With 8.1 and above, we can just use FirstNormalObjectId - 1. + */ + if (fout->remoteVersion < 80100) + g_last_builtin_oid = findLastBuiltinOid_V71(fout); + else + g_last_builtin_oid = FirstNormalObjectId - 1; + + pg_log_info("last built-in OID is %u", g_last_builtin_oid); + + /* Expand schema selection patterns into OID lists */ + if (schema_include_patterns.head != NULL) + { + expand_schema_name_patterns(fout, &schema_include_patterns, + &schema_include_oids, + strict_names); + if (schema_include_oids.head == NULL) + fatal("no matching schemas were found"); + } + expand_schema_name_patterns(fout, &schema_exclude_patterns, + &schema_exclude_oids, + false); + /* non-matching exclusion patterns aren't an error */ + + /* Expand table selection patterns into OID lists */ + if (table_include_patterns.head != NULL) + { + expand_table_name_patterns(fout, &table_include_patterns, + &table_include_oids, + strict_names); + if (table_include_oids.head == NULL) + fatal("no matching tables were found"); + } + expand_table_name_patterns(fout, &table_exclude_patterns, + &table_exclude_oids, + false); + + expand_table_name_patterns(fout, &tabledata_exclude_patterns, + &tabledata_exclude_oids, + false); + + expand_foreign_server_name_patterns(fout, &foreign_servers_include_patterns, + &foreign_servers_include_oids); + + /* non-matching exclusion patterns aren't an error */ + + /* Expand extension selection patterns into OID lists */ + if (extension_include_patterns.head != NULL) + { + expand_extension_name_patterns(fout, &extension_include_patterns, + &extension_include_oids, + strict_names); + if (extension_include_oids.head == NULL) + fatal("no matching extensions were found"); + } + + /* + * Dumping blobs is the default for dumps where an inclusion switch is not + * used (an "include everything" dump). -B can be used to exclude blobs + * from those dumps. -b can be used to include blobs even when an + * inclusion switch is used. + * + * -s means "schema only" and blobs are data, not schema, so we never + * include blobs when -s is used. + */ + if (dopt.include_everything && !dopt.schemaOnly && !dopt.dontOutputBlobs) + dopt.outputBlobs = true; + + /* + * Now scan the database and create DumpableObject structs for all the + * objects we intend to dump. + */ + tblinfo = getSchemaData(fout, &numTables); + + if (fout->remoteVersion < 80400) + guessConstraintInheritance(tblinfo, numTables); + + if (!dopt.schemaOnly) + { + getTableData(&dopt, tblinfo, numTables, 0); + buildMatViewRefreshDependencies(fout); + if (dopt.dataOnly) + getTableDataFKConstraints(); + } + + if (dopt.schemaOnly && dopt.sequence_data) + getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE); + + /* + * In binary-upgrade mode, we do not have to worry about the actual blob + * data or the associated metadata that resides in the pg_largeobject and + * pg_largeobject_metadata tables, respectively. + * + * However, we do need to collect blob information as there may be + * comments or other information on blobs that we do need to dump out. + */ + if (dopt.outputBlobs || dopt.binary_upgrade) + getBlobs(fout); + + /* + * Collect dependency data to assist in ordering the objects. + */ + getDependencies(fout); + + /* Lastly, create dummy objects to represent the section boundaries */ + boundaryObjs = createBoundaryObjects(); + + /* Get pointers to all the known DumpableObjects */ + getDumpableObjects(&dobjs, &numObjs); + + /* + * Add dummy dependencies to enforce the dump section ordering. + */ + addBoundaryDependencies(dobjs, numObjs, boundaryObjs); + + /* + * Sort the objects into a safe dump order (no forward references). + * + * We rely on dependency information to help us determine a safe order, so + * the initial sort is mostly for cosmetic purposes: we sort by name to + * ensure that logically identical schemas will dump identically. + */ + sortDumpableObjectsByTypeName(dobjs, numObjs); + + sortDumpableObjects(dobjs, numObjs, + boundaryObjs[0].dumpId, boundaryObjs[1].dumpId); + + /* + * Create archive TOC entries for all the objects to be dumped, in a safe + * order. + */ + + /* + * First the special entries for ENCODING, STDSTRINGS, and SEARCHPATH. + */ + dumpEncoding(fout); + dumpStdStrings(fout); + dumpSearchPath(fout); + + /* The database items are always next, unless we don't want them at all */ + if (dopt.outputCreateDB) + dumpDatabase(fout); + + /* Now the rearrangeable objects. */ + for (i = 0; i < numObjs; i++) + dumpDumpableObject(fout, dobjs[i]); + + /* + * Set up options info to ensure we dump what we want. + */ + ropt = NewRestoreOptions(); + ropt->filename = filename; + + /* if you change this list, see dumpOptionsFromRestoreOptions */ + ropt->cparams.dbname = dopt.cparams.dbname ? pg_strdup(dopt.cparams.dbname) : NULL; + ropt->cparams.pgport = dopt.cparams.pgport ? pg_strdup(dopt.cparams.pgport) : NULL; + ropt->cparams.pghost = dopt.cparams.pghost ? pg_strdup(dopt.cparams.pghost) : NULL; + ropt->cparams.username = dopt.cparams.username ? pg_strdup(dopt.cparams.username) : NULL; + ropt->cparams.promptPassword = dopt.cparams.promptPassword; + ropt->dropSchema = dopt.outputClean; + ropt->dataOnly = dopt.dataOnly; + ropt->schemaOnly = dopt.schemaOnly; + ropt->if_exists = dopt.if_exists; + ropt->column_inserts = dopt.column_inserts; + ropt->dumpSections = dopt.dumpSections; + ropt->aclsSkip = dopt.aclsSkip; + ropt->superuser = dopt.outputSuperuser; + ropt->createDB = dopt.outputCreateDB; + ropt->noOwner = dopt.outputNoOwner; + ropt->noTablespace = dopt.outputNoTablespaces; + ropt->disable_triggers = dopt.disable_triggers; + ropt->use_setsessauth = dopt.use_setsessauth; + ropt->disable_dollar_quoting = dopt.disable_dollar_quoting; + ropt->dump_inserts = dopt.dump_inserts; + ropt->no_comments = dopt.no_comments; + ropt->no_publications = dopt.no_publications; + ropt->no_security_labels = dopt.no_security_labels; + ropt->no_subscriptions = dopt.no_subscriptions; + ropt->lockWaitTimeout = dopt.lockWaitTimeout; + ropt->include_everything = dopt.include_everything; + ropt->enable_row_security = dopt.enable_row_security; + ropt->sequence_data = dopt.sequence_data; + ropt->binary_upgrade = dopt.binary_upgrade; + + if (compressLevel == -1) + ropt->compression = 0; + else + ropt->compression = compressLevel; + + ropt->suppressDumpWarnings = true; /* We've already shown them */ + + SetArchiveOptions(fout, &dopt, ropt); + + /* Mark which entries should be output */ + ProcessArchiveRestoreOptions(fout); + + /* + * The archive's TOC entries are now marked as to which ones will actually + * be output, so we can set up their dependency lists properly. This isn't + * necessary for plain-text output, though. + */ + if (!plainText) + BuildArchiveDependencies(fout); + + /* + * And finally we can do the actual output. + * + * Note: for non-plain-text output formats, the output file is written + * inside CloseArchive(). This is, um, bizarre; but not worth changing + * right now. + */ + if (plainText) + RestoreArchive(fout); + + CloseArchive(fout); + + exit_nicely(0); +} + + +static void +help(const char *progname) +{ + printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]... [DBNAME]\n"), progname); + + printf(_("\nGeneral options:\n")); + printf(_(" -f, --file=FILENAME output file or directory name\n")); + printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" + " plain text (default))\n")); + printf(_(" -j, --jobs=NUM use this many parallel jobs to dump\n")); + printf(_(" -v, --verbose verbose mode\n")); + printf(_(" -V, --version output version information, then exit\n")); + printf(_(" -Z, --compress=0-9 compression level for compressed formats\n")); + printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n")); + printf(_(" --no-sync do not wait for changes to be written safely to disk\n")); + printf(_(" -?, --help show this help, then exit\n")); + + printf(_("\nOptions controlling the output content:\n")); + printf(_(" -a, --data-only dump only the data, not the schema\n")); + printf(_(" -b, --blobs include large objects in dump\n")); + printf(_(" -B, --no-blobs exclude large objects in dump\n")); + printf(_(" -c, --clean clean (drop) database objects before recreating\n")); + printf(_(" -C, --create include commands to create database in dump\n")); + printf(_(" -e, --extension=PATTERN dump the specified extension(s) only\n")); + printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n")); + printf(_(" -n, --schema=PATTERN dump the specified schema(s) only\n")); + printf(_(" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n")); + printf(_(" -O, --no-owner skip restoration of object ownership in\n" + " plain-text format\n")); + printf(_(" -s, --schema-only dump only the schema, no data\n")); + printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n")); + printf(_(" -t, --table=PATTERN dump the specified table(s) only\n")); + printf(_(" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n")); + printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n")); + printf(_(" --binary-upgrade for use by upgrade utilities only\n")); + printf(_(" --column-inserts dump data as INSERT commands with column names\n")); + printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n")); + printf(_(" --disable-triggers disable triggers during data-only restore\n")); + printf(_(" --enable-row-security enable row security (dump only content user has\n" + " access to)\n")); + printf(_(" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n")); + printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n")); + printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --include-foreign-data=PATTERN\n" + " include data of foreign tables on foreign\n" + " servers matching PATTERN\n")); + printf(_(" --inserts dump data as INSERT commands, rather than COPY\n")); + printf(_(" --load-via-partition-root load partitions via the root table\n")); + printf(_(" --no-comments do not dump comments\n")); + printf(_(" --no-publications do not dump publications\n")); + printf(_(" --no-security-labels do not dump security label assignments\n")); + printf(_(" --no-subscriptions do not dump subscriptions\n")); + printf(_(" --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n")); + printf(_(" --no-tablespaces do not dump tablespace assignments\n")); + printf(_(" --no-toast-compression do not dump TOAST compression methods\n")); + printf(_(" --no-unlogged-table-data do not dump unlogged table data\n")); + printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n")); + printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); + printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n")); + printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n")); + printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n")); + printf(_(" --snapshot=SNAPSHOT use given snapshot for the dump\n")); + printf(_(" --strict-names require table and/or schema include patterns to\n" + " match at least one entity each\n")); + printf(_(" --use-set-session-authorization\n" + " use SET SESSION AUTHORIZATION commands instead of\n" + " ALTER OWNER commands to set ownership\n")); + + printf(_("\nConnection options:\n")); + printf(_(" -d, --dbname=DBNAME database to dump\n")); + printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); + printf(_(" -p, --port=PORT database server port number\n")); + printf(_(" -U, --username=NAME connect as specified database user\n")); + printf(_(" -w, --no-password never prompt for password\n")); + printf(_(" -W, --password force password prompt (should happen automatically)\n")); + printf(_(" --role=ROLENAME do SET ROLE before dump\n")); + + printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n" + "variable value is used.\n\n")); + printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); + printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); +} + +static void +setup_connection(Archive *AH, const char *dumpencoding, + const char *dumpsnapshot, char *use_role) +{ + DumpOptions *dopt = AH->dopt; + PGconn *conn = GetConnection(AH); + const char *std_strings; + + PQclear(ExecuteSqlQueryForSingleRow(AH, ALWAYS_SECURE_SEARCH_PATH_SQL)); + + /* + * Set the client encoding if requested. + */ + if (dumpencoding) + { + if (PQsetClientEncoding(conn, dumpencoding) < 0) + fatal("invalid client encoding \"%s\" specified", + dumpencoding); + } + + /* + * Get the active encoding and the standard_conforming_strings setting, so + * we know how to escape strings. + */ + AH->encoding = PQclientEncoding(conn); + + std_strings = PQparameterStatus(conn, "standard_conforming_strings"); + AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0); + + /* + * Set the role if requested. In a parallel dump worker, we'll be passed + * use_role == NULL, but AH->use_role is already set (if user specified it + * originally) and we should use that. + */ + if (!use_role && AH->use_role) + use_role = AH->use_role; + + /* Set the role if requested */ + if (use_role && AH->remoteVersion >= 80100) + { + PQExpBuffer query = createPQExpBuffer(); + + appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role)); + ExecuteSqlStatement(AH, query->data); + destroyPQExpBuffer(query); + + /* save it for possible later use by parallel workers */ + if (!AH->use_role) + AH->use_role = pg_strdup(use_role); + } + + /* Set the datestyle to ISO to ensure the dump's portability */ + ExecuteSqlStatement(AH, "SET DATESTYLE = ISO"); + + /* Likewise, avoid using sql_standard intervalstyle */ + if (AH->remoteVersion >= 80400) + ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES"); + + /* + * Use an explicitly specified extra_float_digits if it has been provided. + * Otherwise, set extra_float_digits so that we can dump float data + * exactly (given correctly implemented float I/O code, anyway). + */ + if (have_extra_float_digits) + { + PQExpBuffer q = createPQExpBuffer(); + + appendPQExpBuffer(q, "SET extra_float_digits TO %d", + extra_float_digits); + ExecuteSqlStatement(AH, q->data); + destroyPQExpBuffer(q); + } + else if (AH->remoteVersion >= 90000) + ExecuteSqlStatement(AH, "SET extra_float_digits TO 3"); + else + ExecuteSqlStatement(AH, "SET extra_float_digits TO 2"); + + /* + * If synchronized scanning is supported, disable it, to prevent + * unpredictable changes in row ordering across a dump and reload. + */ + if (AH->remoteVersion >= 80300) + ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off"); + + /* + * Disable timeouts if supported. + */ + ExecuteSqlStatement(AH, "SET statement_timeout = 0"); + if (AH->remoteVersion >= 90300) + ExecuteSqlStatement(AH, "SET lock_timeout = 0"); + if (AH->remoteVersion >= 90600) + ExecuteSqlStatement(AH, "SET idle_in_transaction_session_timeout = 0"); + + /* + * Quote all identifiers, if requested. + */ + if (quote_all_identifiers && AH->remoteVersion >= 90100) + ExecuteSqlStatement(AH, "SET quote_all_identifiers = true"); + + /* + * Adjust row-security mode, if supported. + */ + if (AH->remoteVersion >= 90500) + { + if (dopt->enable_row_security) + ExecuteSqlStatement(AH, "SET row_security = on"); + else + ExecuteSqlStatement(AH, "SET row_security = off"); + } + + /* + * Start transaction-snapshot mode transaction to dump consistent data. + */ + ExecuteSqlStatement(AH, "BEGIN"); + if (AH->remoteVersion >= 90100) + { + /* + * To support the combination of serializable_deferrable with the jobs + * option we use REPEATABLE READ for the worker connections that are + * passed a snapshot. As long as the snapshot is acquired in a + * SERIALIZABLE, READ ONLY, DEFERRABLE transaction, its use within a + * REPEATABLE READ transaction provides the appropriate integrity + * guarantees. This is a kluge, but safe for back-patching. + */ + if (dopt->serializable_deferrable && AH->sync_snapshot_id == NULL) + ExecuteSqlStatement(AH, + "SET TRANSACTION ISOLATION LEVEL " + "SERIALIZABLE, READ ONLY, DEFERRABLE"); + else + ExecuteSqlStatement(AH, + "SET TRANSACTION ISOLATION LEVEL " + "REPEATABLE READ, READ ONLY"); + } + else + { + ExecuteSqlStatement(AH, + "SET TRANSACTION ISOLATION LEVEL " + "SERIALIZABLE, READ ONLY"); + } + + /* + * If user specified a snapshot to use, select that. In a parallel dump + * worker, we'll be passed dumpsnapshot == NULL, but AH->sync_snapshot_id + * is already set (if the server can handle it) and we should use that. + */ + if (dumpsnapshot) + AH->sync_snapshot_id = pg_strdup(dumpsnapshot); + + if (AH->sync_snapshot_id) + { + PQExpBuffer query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT "); + appendStringLiteralConn(query, AH->sync_snapshot_id, conn); + ExecuteSqlStatement(AH, query->data); + destroyPQExpBuffer(query); + } + else if (AH->numWorkers > 1 && + AH->remoteVersion >= 90200 && + !dopt->no_synchronized_snapshots) + { + if (AH->isStandby && AH->remoteVersion < 100000) + fatal("Synchronized snapshots on standby servers are not supported by this server version.\n" + "Run with --no-synchronized-snapshots instead if you do not need\n" + "synchronized snapshots."); + + + AH->sync_snapshot_id = get_synchronized_snapshot(AH); + } +} + +/* Set up connection for a parallel worker process */ +static void +setupDumpWorker(Archive *AH) +{ + /* + * We want to re-select all the same values the leader connection is + * using. We'll have inherited directly-usable values in + * AH->sync_snapshot_id and AH->use_role, but we need to translate the + * inherited encoding value back to a string to pass to setup_connection. + */ + setup_connection(AH, + pg_encoding_to_char(AH->encoding), + NULL, + NULL); +} + +static char * +get_synchronized_snapshot(Archive *fout) +{ + char *query = "SELECT pg_catalog.pg_export_snapshot()"; + char *result; + PGresult *res; + + res = ExecuteSqlQueryForSingleRow(fout, query); + result = pg_strdup(PQgetvalue(res, 0, 0)); + PQclear(res); + + return result; +} + +static ArchiveFormat +parseArchiveFormat(const char *format, ArchiveMode *mode) +{ + ArchiveFormat archiveFormat; + + *mode = archModeWrite; + + if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0) + { + /* This is used by pg_dumpall, and is not documented */ + archiveFormat = archNull; + *mode = archModeAppend; + } + else if (pg_strcasecmp(format, "c") == 0) + archiveFormat = archCustom; + else if (pg_strcasecmp(format, "custom") == 0) + archiveFormat = archCustom; + else if (pg_strcasecmp(format, "d") == 0) + archiveFormat = archDirectory; + else if (pg_strcasecmp(format, "directory") == 0) + archiveFormat = archDirectory; + else if (pg_strcasecmp(format, "p") == 0) + archiveFormat = archNull; + else if (pg_strcasecmp(format, "plain") == 0) + archiveFormat = archNull; + else if (pg_strcasecmp(format, "t") == 0) + archiveFormat = archTar; + else if (pg_strcasecmp(format, "tar") == 0) + archiveFormat = archTar; + else + fatal("invalid output format \"%s\" specified", format); + return archiveFormat; +} + +/* + * Find the OIDs of all schemas matching the given list of patterns, + * and append them to the given OID list. + */ +static void +expand_schema_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names) +{ + PQExpBuffer query; + PGresult *res; + SimpleStringListCell *cell; + int i; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * The loop below runs multiple SELECTs might sometimes result in + * duplicate entries in the OID list, but we don't care. + */ + + for (cell = patterns->head; cell; cell = cell->next) + { + PQExpBufferData dbbuf; + int dotcnt; + + appendPQExpBufferStr(query, + "SELECT oid FROM pg_catalog.pg_namespace n\n"); + initPQExpBuffer(&dbbuf); + processSQLNamePattern(GetConnection(fout), query, cell->val, false, + false, NULL, "n.nspname", NULL, NULL, &dbbuf, + &dotcnt); + if (dotcnt > 1) + fatal("improper qualified name (too many dotted names): %s", + cell->val); + else if (dotcnt == 1) + prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val); + termPQExpBuffer(&dbbuf); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + if (strict_names && PQntuples(res) == 0) + fatal("no matching schemas were found for pattern \"%s\"", cell->val); + + for (i = 0; i < PQntuples(res); i++) + { + simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0))); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} + +/* + * Find the OIDs of all extensions matching the given list of patterns, + * and append them to the given OID list. + */ +static void +expand_extension_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names) +{ + PQExpBuffer query; + PGresult *res; + SimpleStringListCell *cell; + int i; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * The loop below runs multiple SELECTs might sometimes result in + * duplicate entries in the OID list, but we don't care. + */ + for (cell = patterns->head; cell; cell = cell->next) + { + int dotcnt; + + appendPQExpBufferStr(query, + "SELECT oid FROM pg_catalog.pg_extension e\n"); + processSQLNamePattern(GetConnection(fout), query, cell->val, false, + false, NULL, "e.extname", NULL, NULL, NULL, + &dotcnt); + if (dotcnt > 0) + fatal("improper qualified name (too many dotted names): %s", + cell->val); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + if (strict_names && PQntuples(res) == 0) + fatal("no matching extensions were found for pattern \"%s\"", cell->val); + + for (i = 0; i < PQntuples(res); i++) + { + simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0))); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} + +/* + * Find the OIDs of all foreign servers matching the given list of patterns, + * and append them to the given OID list. + */ +static void +expand_foreign_server_name_patterns(Archive *fout, + SimpleStringList *patterns, + SimpleOidList *oids) +{ + PQExpBuffer query; + PGresult *res; + SimpleStringListCell *cell; + int i; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * The loop below runs multiple SELECTs might sometimes result in + * duplicate entries in the OID list, but we don't care. + */ + + for (cell = patterns->head; cell; cell = cell->next) + { + int dotcnt; + + appendPQExpBufferStr(query, + "SELECT oid FROM pg_catalog.pg_foreign_server s\n"); + processSQLNamePattern(GetConnection(fout), query, cell->val, false, + false, NULL, "s.srvname", NULL, NULL, NULL, + &dotcnt); + if (dotcnt > 0) + fatal("improper qualified name (too many dotted names): %s", + cell->val); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + if (PQntuples(res) == 0) + fatal("no matching foreign servers were found for pattern \"%s\"", cell->val); + + for (i = 0; i < PQntuples(res); i++) + simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0))); + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} + +/* + * Find the OIDs of all tables matching the given list of patterns, + * and append them to the given OID list. See also expand_dbname_patterns() + * in pg_dumpall.c + */ +static void +expand_table_name_patterns(Archive *fout, + SimpleStringList *patterns, SimpleOidList *oids, + bool strict_names) +{ + PQExpBuffer query; + PGresult *res; + SimpleStringListCell *cell; + int i; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * this might sometimes result in duplicate entries in the OID list, but + * we don't care. + */ + + for (cell = patterns->head; cell; cell = cell->next) + { + PQExpBufferData dbbuf; + int dotcnt; + + /* + * Query must remain ABSOLUTELY devoid of unqualified names. This + * would be unnecessary given a pg_table_is_visible() variant taking a + * search_path argument. + */ + appendPQExpBuffer(query, + "SELECT c.oid" + "\nFROM pg_catalog.pg_class c" + "\n LEFT JOIN pg_catalog.pg_namespace n" + "\n ON n.oid OPERATOR(pg_catalog.=) c.relnamespace" + "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY" + "\n (array['%c', '%c', '%c', '%c', '%c', '%c'])\n", + RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE, + RELKIND_PARTITIONED_TABLE); + initPQExpBuffer(&dbbuf); + processSQLNamePattern(GetConnection(fout), query, cell->val, true, + false, "n.nspname", "c.relname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)", &dbbuf, + &dotcnt); + if (dotcnt > 2) + fatal("improper relation name (too many dotted names): %s", + cell->val); + else if (dotcnt == 2) + prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val); + termPQExpBuffer(&dbbuf); + + ExecuteSqlStatement(fout, "RESET search_path"); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + PQclear(ExecuteSqlQueryForSingleRow(fout, + ALWAYS_SECURE_SEARCH_PATH_SQL)); + if (strict_names && PQntuples(res) == 0) + fatal("no matching tables were found for pattern \"%s\"", cell->val); + + for (i = 0; i < PQntuples(res); i++) + { + simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0))); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} + +/* + * Verifies that the connected database name matches the given database name, + * and if not, dies with an error about the given pattern. + * + * The 'dbname' argument should be a literal name parsed from 'pattern'. + */ +static void +prohibit_crossdb_refs(PGconn *conn, const char *dbname, const char *pattern) +{ + const char *db; + + db = PQdb(conn); + if (db == NULL) + fatal("You are currently not connected to a database."); + + if (strcmp(db, dbname) != 0) + fatal("cross-database references are not implemented: %s", pattern); +} + +/* + * checkExtensionMembership + * Determine whether object is an extension member, and if so, + * record an appropriate dependency and set the object's dump flag. + * + * It's important to call this for each object that could be an extension + * member. Generally, we integrate this with determining the object's + * to-be-dumped-ness, since extension membership overrides other rules for that. + * + * Returns true if object is an extension member, else false. + */ +static bool +checkExtensionMembership(DumpableObject *dobj, Archive *fout) +{ + ExtensionInfo *ext = findOwningExtension(dobj->catId); + + if (ext == NULL) + return false; + + dobj->ext_member = true; + + /* Record dependency so that getDependencies needn't deal with that */ + addObjectDependency(dobj, ext->dobj.dumpId); + + /* + * In 9.6 and above, mark the member object to have any non-initial ACL, + * policies, and security labels dumped. + * + * Note that any initial ACLs (see pg_init_privs) will be removed when we + * extract the information about the object. We don't provide support for + * initial policies and security labels and it seems unlikely for those to + * ever exist, but we may have to revisit this later. + * + * Prior to 9.6, we do not include any extension member components. + * + * In binary upgrades, we still dump all components of the members + * individually, since the idea is to exactly reproduce the database + * contents rather than replace the extension contents with something + * different. + */ + if (fout->dopt->binary_upgrade) + dobj->dump = ext->dobj.dump; + else + { + if (fout->remoteVersion < 90600) + dobj->dump = DUMP_COMPONENT_NONE; + else + dobj->dump = ext->dobj.dump_contains & (DUMP_COMPONENT_ACL | + DUMP_COMPONENT_SECLABEL | + DUMP_COMPONENT_POLICY); + } + + return true; +} + +/* + * selectDumpableNamespace: policy-setting subroutine + * Mark a namespace as to be dumped or not + */ +static void +selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout) +{ + /* + * If specific tables are being dumped, do not dump any complete + * namespaces. If specific namespaces are being dumped, dump just those + * namespaces. Otherwise, dump all non-system namespaces. + */ + if (table_include_oids.head != NULL) + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE; + else if (schema_include_oids.head != NULL) + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = + simple_oid_list_member(&schema_include_oids, + nsinfo->dobj.catId.oid) ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; + else if (fout->remoteVersion >= 90600 && + strcmp(nsinfo->dobj.name, "pg_catalog") == 0) + { + /* + * In 9.6 and above, we dump out any ACLs defined in pg_catalog, if + * they are interesting (and not the original ACLs which were set at + * initdb time, see pg_init_privs). + */ + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ACL; + } + else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 || + strcmp(nsinfo->dobj.name, "information_schema") == 0) + { + /* Other system schemas don't get dumped */ + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE; + } + else if (strcmp(nsinfo->dobj.name, "public") == 0) + { + /* + * The public schema is a strange beast that sits in a sort of + * no-mans-land between being a system object and a user object. We + * don't want to dump creation or comment commands for it, because + * that complicates matters for non-superuser use of pg_dump. But we + * should dump any ACL changes that have occurred for it, and of + * course we should dump contained objects. + */ + nsinfo->dobj.dump = DUMP_COMPONENT_ACL; + nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL; + } + else + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL; + + /* + * In any case, a namespace can be excluded by an exclusion switch + */ + if (nsinfo->dobj.dump_contains && + simple_oid_list_member(&schema_exclude_oids, + nsinfo->dobj.catId.oid)) + nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE; + + /* + * If the schema belongs to an extension, allow extension membership to + * override the dump decision for the schema itself. However, this does + * not change dump_contains, so this won't change what we do with objects + * within the schema. (If they belong to the extension, they'll get + * suppressed by it, otherwise not.) + */ + (void) checkExtensionMembership(&nsinfo->dobj, fout); +} + +/* + * selectDumpableTable: policy-setting subroutine + * Mark a table as to be dumped or not + */ +static void +selectDumpableTable(TableInfo *tbinfo, Archive *fout) +{ + if (checkExtensionMembership(&tbinfo->dobj, fout)) + return; /* extension membership overrides all else */ + + /* + * If specific tables are being dumped, dump just those tables; else, dump + * according to the parent namespace's dump flag. + */ + if (table_include_oids.head != NULL) + tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids, + tbinfo->dobj.catId.oid) ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; + else + tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump_contains; + + /* + * In any case, a table can be excluded by an exclusion switch + */ + if (tbinfo->dobj.dump && + simple_oid_list_member(&table_exclude_oids, + tbinfo->dobj.catId.oid)) + tbinfo->dobj.dump = DUMP_COMPONENT_NONE; +} + +/* + * selectDumpableType: policy-setting subroutine + * Mark a type as to be dumped or not + * + * If it's a table's rowtype or an autogenerated array type, we also apply a + * special type code to facilitate sorting into the desired order. (We don't + * want to consider those to be ordinary types because that would bring tables + * up into the datatype part of the dump order.) We still set the object's + * dump flag; that's not going to cause the dummy type to be dumped, but we + * need it so that casts involving such types will be dumped correctly -- see + * dumpCast. This means the flag should be set the same as for the underlying + * object (the table or base type). + */ +static void +selectDumpableType(TypeInfo *tyinfo, Archive *fout) +{ + /* skip complex types, except for standalone composite types */ + if (OidIsValid(tyinfo->typrelid) && + tyinfo->typrelkind != RELKIND_COMPOSITE_TYPE) + { + TableInfo *tytable = findTableByOid(tyinfo->typrelid); + + tyinfo->dobj.objType = DO_DUMMY_TYPE; + if (tytable != NULL) + tyinfo->dobj.dump = tytable->dobj.dump; + else + tyinfo->dobj.dump = DUMP_COMPONENT_NONE; + return; + } + + /* skip auto-generated array types */ + if (tyinfo->isArray || tyinfo->isMultirange) + { + tyinfo->dobj.objType = DO_DUMMY_TYPE; + + /* + * Fall through to set the dump flag; we assume that the subsequent + * rules will do the same thing as they would for the array's base + * type. (We cannot reliably look up the base type here, since + * getTypes may not have processed it yet.) + */ + } + + if (checkExtensionMembership(&tyinfo->dobj, fout)) + return; /* extension membership overrides all else */ + + /* Dump based on if the contents of the namespace are being dumped */ + tyinfo->dobj.dump = tyinfo->dobj.namespace->dobj.dump_contains; +} + +/* + * selectDumpableDefaultACL: policy-setting subroutine + * Mark a default ACL as to be dumped or not + * + * For per-schema default ACLs, dump if the schema is to be dumped. + * Otherwise dump if we are dumping "everything". Note that dataOnly + * and aclsSkip are checked separately. + */ +static void +selectDumpableDefaultACL(DefaultACLInfo *dinfo, DumpOptions *dopt) +{ + /* Default ACLs can't be extension members */ + + if (dinfo->dobj.namespace) + /* default ACLs are considered part of the namespace */ + dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump_contains; + else + dinfo->dobj.dump = dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; +} + +/* + * selectDumpableCast: policy-setting subroutine + * Mark a cast as to be dumped or not + * + * Casts do not belong to any particular namespace (since they haven't got + * names), nor do they have identifiable owners. To distinguish user-defined + * casts from built-in ones, we must resort to checking whether the cast's + * OID is in the range reserved for initdb. + */ +static void +selectDumpableCast(CastInfo *cast, Archive *fout) +{ + if (checkExtensionMembership(&cast->dobj, fout)) + return; /* extension membership overrides all else */ + + /* + * This would be DUMP_COMPONENT_ACL for from-initdb casts, but they do not + * support ACLs currently. + */ + if (cast->dobj.catId.oid <= (Oid) g_last_builtin_oid) + cast->dobj.dump = DUMP_COMPONENT_NONE; + else + cast->dobj.dump = fout->dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; +} + +/* + * selectDumpableProcLang: policy-setting subroutine + * Mark a procedural language as to be dumped or not + * + * Procedural languages do not belong to any particular namespace. To + * identify built-in languages, we must resort to checking whether the + * language's OID is in the range reserved for initdb. + */ +static void +selectDumpableProcLang(ProcLangInfo *plang, Archive *fout) +{ + if (checkExtensionMembership(&plang->dobj, fout)) + return; /* extension membership overrides all else */ + + /* + * Only include procedural languages when we are dumping everything. + * + * For from-initdb procedural languages, only include ACLs, as we do for + * the pg_catalog namespace. We need this because procedural languages do + * not live in any namespace. + */ + if (!fout->dopt->include_everything) + plang->dobj.dump = DUMP_COMPONENT_NONE; + else + { + if (plang->dobj.catId.oid <= (Oid) g_last_builtin_oid) + plang->dobj.dump = fout->remoteVersion < 90600 ? + DUMP_COMPONENT_NONE : DUMP_COMPONENT_ACL; + else + plang->dobj.dump = DUMP_COMPONENT_ALL; + } +} + +/* + * selectDumpableAccessMethod: policy-setting subroutine + * Mark an access method as to be dumped or not + * + * Access methods do not belong to any particular namespace. To identify + * built-in access methods, we must resort to checking whether the + * method's OID is in the range reserved for initdb. + */ +static void +selectDumpableAccessMethod(AccessMethodInfo *method, Archive *fout) +{ + if (checkExtensionMembership(&method->dobj, fout)) + return; /* extension membership overrides all else */ + + /* + * This would be DUMP_COMPONENT_ACL for from-initdb access methods, but + * they do not support ACLs currently. + */ + if (method->dobj.catId.oid <= (Oid) g_last_builtin_oid) + method->dobj.dump = DUMP_COMPONENT_NONE; + else + method->dobj.dump = fout->dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; +} + +/* + * selectDumpableExtension: policy-setting subroutine + * Mark an extension as to be dumped or not + * + * Built-in extensions should be skipped except for checking ACLs, since we + * assume those will already be installed in the target database. We identify + * such extensions by their having OIDs in the range reserved for initdb. + * We dump all user-added extensions by default. No extensions are dumped + * if include_everything is false (i.e., a --schema or --table switch was + * given), except if --extension specifies a list of extensions to dump. + */ +static void +selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt) +{ + /* + * Use DUMP_COMPONENT_ACL for built-in extensions, to allow users to + * change permissions on their member objects, if they wish to, and have + * those changes preserved. + */ + if (extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid) + extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL; + else + { + /* check if there is a list of extensions to dump */ + if (extension_include_oids.head != NULL) + extinfo->dobj.dump = extinfo->dobj.dump_contains = + simple_oid_list_member(&extension_include_oids, + extinfo->dobj.catId.oid) ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; + else + extinfo->dobj.dump = extinfo->dobj.dump_contains = + dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; + } +} + +/* + * selectDumpablePublicationTable: policy-setting subroutine + * Mark a publication table as to be dumped or not + * + * Publication tables have schemas, but those are ignored in decision making, + * because publications are only dumped when we are dumping everything. + */ +static void +selectDumpablePublicationTable(DumpableObject *dobj, Archive *fout) +{ + if (checkExtensionMembership(dobj, fout)) + return; /* extension membership overrides all else */ + + dobj->dump = fout->dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; +} + +/* + * selectDumpableObject: policy-setting subroutine + * Mark a generic dumpable object as to be dumped or not + * + * Use this only for object types without a special-case routine above. + */ +static void +selectDumpableObject(DumpableObject *dobj, Archive *fout) +{ + if (checkExtensionMembership(dobj, fout)) + return; /* extension membership overrides all else */ + + /* + * Default policy is to dump if parent namespace is dumpable, or for + * non-namespace-associated items, dump if we're dumping "everything". + */ + if (dobj->namespace) + dobj->dump = dobj->namespace->dobj.dump_contains; + else + dobj->dump = fout->dopt->include_everything ? + DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE; +} + +/* + * Dump a table's contents for loading using the COPY command + * - this routine is called by the Archiver when it wants the table + * to be dumped. + */ +static int +dumpTableData_copy(Archive *fout, const void *dcontext) +{ + TableDataInfo *tdinfo = (TableDataInfo *) dcontext; + TableInfo *tbinfo = tdinfo->tdtable; + const char *classname = tbinfo->dobj.name; + PQExpBuffer q = createPQExpBuffer(); + + /* + * Note: can't use getThreadLocalPQExpBuffer() here, we're calling fmtId + * which uses it already. + */ + PQExpBuffer clistBuf = createPQExpBuffer(); + PGconn *conn = GetConnection(fout); + PGresult *res; + int ret; + char *copybuf; + const char *column_list; + + pg_log_info("dumping contents of table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, classname); + + /* + * Specify the column list explicitly so that we have no possibility of + * retrieving data in the wrong column order. (The default column + * ordering of COPY will not be what we want in certain corner cases + * involving ADD COLUMN and inheritance.) + */ + column_list = fmtCopyColumnList(tbinfo, clistBuf); + + /* + * Use COPY (SELECT ...) TO when dumping a foreign table's data, and when + * a filter condition was specified. For other cases a simple COPY + * suffices. + */ + if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE) + { + /* Note: this syntax is only supported in 8.2 and up */ + appendPQExpBufferStr(q, "COPY (SELECT "); + /* klugery to get rid of parens in column list */ + if (strlen(column_list) > 2) + { + appendPQExpBufferStr(q, column_list + 1); + q->data[q->len - 1] = ' '; + } + else + appendPQExpBufferStr(q, "* "); + + appendPQExpBuffer(q, "FROM %s %s) TO stdout;", + fmtQualifiedDumpable(tbinfo), + tdinfo->filtercond ? tdinfo->filtercond : ""); + } + else + { + appendPQExpBuffer(q, "COPY %s %s TO stdout;", + fmtQualifiedDumpable(tbinfo), + column_list); + } + res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT); + PQclear(res); + destroyPQExpBuffer(clistBuf); + + for (;;) + { + ret = PQgetCopyData(conn, ©buf, 0); + + if (ret < 0) + break; /* done or error */ + + if (copybuf) + { + WriteData(fout, copybuf, ret); + PQfreemem(copybuf); + } + + /* ---------- + * THROTTLE: + * + * There was considerable discussion in late July, 2000 regarding + * slowing down pg_dump when backing up large tables. Users with both + * slow & fast (multi-processor) machines experienced performance + * degradation when doing a backup. + * + * Initial attempts based on sleeping for a number of ms for each ms + * of work were deemed too complex, then a simple 'sleep in each loop' + * implementation was suggested. The latter failed because the loop + * was too tight. Finally, the following was implemented: + * + * If throttle is non-zero, then + * See how long since the last sleep. + * Work out how long to sleep (based on ratio). + * If sleep is more than 100ms, then + * sleep + * reset timer + * EndIf + * EndIf + * + * where the throttle value was the number of ms to sleep per ms of + * work. The calculation was done in each loop. + * + * Most of the hard work is done in the backend, and this solution + * still did not work particularly well: on slow machines, the ratio + * was 50:1, and on medium paced machines, 1:1, and on fast + * multi-processor machines, it had little or no effect, for reasons + * that were unclear. + * + * Further discussion ensued, and the proposal was dropped. + * + * For those people who want this feature, it can be implemented using + * gettimeofday in each loop, calculating the time since last sleep, + * multiplying that by the sleep ratio, then if the result is more + * than a preset 'minimum sleep time' (say 100ms), call the 'select' + * function to sleep for a subsecond period ie. + * + * select(0, NULL, NULL, NULL, &tvi); + * + * This will return after the interval specified in the structure tvi. + * Finally, call gettimeofday again to save the 'last sleep time'. + * ---------- + */ + } + archprintf(fout, "\\.\n\n\n"); + + if (ret == -2) + { + /* copy data transfer failed */ + pg_log_error("Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.", classname); + pg_log_error("Error message from server: %s", PQerrorMessage(conn)); + pg_log_error("The command was: %s", q->data); + exit_nicely(1); + } + + /* Check command status and return to normal libpq state */ + res = PQgetResult(conn); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + pg_log_error("Dumping the contents of table \"%s\" failed: PQgetResult() failed.", classname); + pg_log_error("Error message from server: %s", PQerrorMessage(conn)); + pg_log_error("The command was: %s", q->data); + exit_nicely(1); + } + PQclear(res); + + /* Do this to ensure we've pumped libpq back to idle state */ + if (PQgetResult(conn) != NULL) + pg_log_warning("unexpected extra results during COPY of table \"%s\"", + classname); + + destroyPQExpBuffer(q); + return 1; +} + +/* + * Dump table data using INSERT commands. + * + * Caution: when we restore from an archive file direct to database, the + * INSERT commands emitted by this function have to be parsed by + * pg_backup_db.c's ExecuteSimpleCommands(), which will not handle comments, + * E'' strings, or dollar-quoted strings. So don't emit anything like that. + */ +static int +dumpTableData_insert(Archive *fout, const void *dcontext) +{ + TableDataInfo *tdinfo = (TableDataInfo *) dcontext; + TableInfo *tbinfo = tdinfo->tdtable; + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer insertStmt = NULL; + char *attgenerated; + PGresult *res; + int nfields, + i; + int rows_per_statement = dopt->dump_inserts; + int rows_this_statement = 0; + + /* + * If we're going to emit INSERTs with column names, the most efficient + * way to deal with generated columns is to exclude them entirely. For + * INSERTs without column names, we have to emit DEFAULT rather than the + * actual column value --- but we can save a few cycles by fetching nulls + * rather than the uninteresting-to-us value. + */ + attgenerated = (char *) pg_malloc(tbinfo->numatts * sizeof(char)); + appendPQExpBufferStr(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT "); + nfields = 0; + for (i = 0; i < tbinfo->numatts; i++) + { + if (tbinfo->attisdropped[i]) + continue; + if (tbinfo->attgenerated[i] && dopt->column_inserts) + continue; + if (nfields > 0) + appendPQExpBufferStr(q, ", "); + if (tbinfo->attgenerated[i]) + appendPQExpBufferStr(q, "NULL"); + else + appendPQExpBufferStr(q, fmtId(tbinfo->attnames[i])); + attgenerated[nfields] = tbinfo->attgenerated[i]; + nfields++; + } + /* Servers before 9.4 will complain about zero-column SELECT */ + if (nfields == 0) + appendPQExpBufferStr(q, "NULL"); + appendPQExpBuffer(q, " FROM ONLY %s", + fmtQualifiedDumpable(tbinfo)); + if (tdinfo->filtercond) + appendPQExpBuffer(q, " %s", tdinfo->filtercond); + + ExecuteSqlStatement(fout, q->data); + + while (1) + { + res = ExecuteSqlQuery(fout, "FETCH 100 FROM _pg_dump_cursor", + PGRES_TUPLES_OK); + + /* cross-check field count, allowing for dummy NULL if any */ + if (nfields != PQnfields(res) && + !(nfields == 0 && PQnfields(res) == 1)) + fatal("wrong number of fields retrieved from table \"%s\"", + tbinfo->dobj.name); + + /* + * First time through, we build as much of the INSERT statement as + * possible in "insertStmt", which we can then just print for each + * statement. If the table happens to have zero dumpable columns then + * this will be a complete statement, otherwise it will end in + * "VALUES" and be ready to have the row's column values printed. + */ + if (insertStmt == NULL) + { + TableInfo *targettab; + + insertStmt = createPQExpBuffer(); + + /* + * When load-via-partition-root is set, get the root table name + * for the partition table, so that we can reload data through the + * root table. + */ + if (dopt->load_via_partition_root && tbinfo->ispartition) + targettab = getRootTableInfo(tbinfo); + else + targettab = tbinfo; + + appendPQExpBuffer(insertStmt, "INSERT INTO %s ", + fmtQualifiedDumpable(targettab)); + + /* corner case for zero-column table */ + if (nfields == 0) + { + appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n"); + } + else + { + /* append the list of column names if required */ + if (dopt->column_inserts) + { + appendPQExpBufferChar(insertStmt, '('); + for (int field = 0; field < nfields; field++) + { + if (field > 0) + appendPQExpBufferStr(insertStmt, ", "); + appendPQExpBufferStr(insertStmt, + fmtId(PQfname(res, field))); + } + appendPQExpBufferStr(insertStmt, ") "); + } + + if (tbinfo->needs_override) + appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE "); + + appendPQExpBufferStr(insertStmt, "VALUES"); + } + } + + for (int tuple = 0; tuple < PQntuples(res); tuple++) + { + /* Write the INSERT if not in the middle of a multi-row INSERT. */ + if (rows_this_statement == 0) + archputs(insertStmt->data, fout); + + /* + * If it is zero-column table then we've already written the + * complete statement, which will mean we've disobeyed + * --rows-per-insert when it's set greater than 1. We do support + * a way to make this multi-row with: SELECT UNION ALL SELECT + * UNION ALL ... but that's non-standard so we should avoid it + * given that using INSERTs is mostly only ever needed for + * cross-database exports. + */ + if (nfields == 0) + continue; + + /* Emit a row heading */ + if (rows_per_statement == 1) + archputs(" (", fout); + else if (rows_this_statement > 0) + archputs(",\n\t(", fout); + else + archputs("\n\t(", fout); + + for (int field = 0; field < nfields; field++) + { + if (field > 0) + archputs(", ", fout); + if (attgenerated[field]) + { + archputs("DEFAULT", fout); + continue; + } + if (PQgetisnull(res, tuple, field)) + { + archputs("NULL", fout); + continue; + } + + /* XXX This code is partially duplicated in ruleutils.c */ + switch (PQftype(res, field)) + { + case INT2OID: + case INT4OID: + case INT8OID: + case OIDOID: + case FLOAT4OID: + case FLOAT8OID: + case NUMERICOID: + { + /* + * These types are printed without quotes unless + * they contain values that aren't accepted by the + * scanner unquoted (e.g., 'NaN'). Note that + * strtod() and friends might accept NaN, so we + * can't use that to test. + * + * In reality we only need to defend against + * infinity and NaN, so we need not get too crazy + * about pattern matching here. + */ + const char *s = PQgetvalue(res, tuple, field); + + if (strspn(s, "0123456789 +-eE.") == strlen(s)) + archputs(s, fout); + else + archprintf(fout, "'%s'", s); + } + break; + + case BITOID: + case VARBITOID: + archprintf(fout, "B'%s'", + PQgetvalue(res, tuple, field)); + break; + + case BOOLOID: + if (strcmp(PQgetvalue(res, tuple, field), "t") == 0) + archputs("true", fout); + else + archputs("false", fout); + break; + + default: + /* All other types are printed as string literals. */ + resetPQExpBuffer(q); + appendStringLiteralAH(q, + PQgetvalue(res, tuple, field), + fout); + archputs(q->data, fout); + break; + } + } + + /* Terminate the row ... */ + archputs(")", fout); + + /* ... and the statement, if the target no. of rows is reached */ + if (++rows_this_statement >= rows_per_statement) + { + if (dopt->do_nothing) + archputs(" ON CONFLICT DO NOTHING;\n", fout); + else + archputs(";\n", fout); + /* Reset the row counter */ + rows_this_statement = 0; + } + } + + if (PQntuples(res) <= 0) + { + PQclear(res); + break; + } + PQclear(res); + } + + /* Terminate any statements that didn't make the row count. */ + if (rows_this_statement > 0) + { + if (dopt->do_nothing) + archputs(" ON CONFLICT DO NOTHING;\n", fout); + else + archputs(";\n", fout); + } + + archputs("\n\n", fout); + + ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor"); + + destroyPQExpBuffer(q); + if (insertStmt != NULL) + destroyPQExpBuffer(insertStmt); + free(attgenerated); + + return 1; +} + +/* + * getRootTableInfo: + * get the root TableInfo for the given partition table. + */ +static TableInfo * +getRootTableInfo(const TableInfo *tbinfo) +{ + TableInfo *parentTbinfo; + + Assert(tbinfo->ispartition); + Assert(tbinfo->numParents == 1); + + parentTbinfo = tbinfo->parents[0]; + while (parentTbinfo->ispartition) + { + Assert(parentTbinfo->numParents == 1); + parentTbinfo = parentTbinfo->parents[0]; + } + + return parentTbinfo; +} + +/* + * dumpTableData - + * dump the contents of a single table + * + * Actually, this just makes an ArchiveEntry for the table contents. + */ +static void +dumpTableData(Archive *fout, const TableDataInfo *tdinfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = tdinfo->tdtable; + PQExpBuffer copyBuf = createPQExpBuffer(); + PQExpBuffer clistBuf = createPQExpBuffer(); + DataDumperPtr dumpFn; + char *copyStmt; + const char *copyFrom; + + /* We had better have loaded per-column details about this table */ + Assert(tbinfo->interesting); + + if (dopt->dump_inserts == 0) + { + /* Dump/restore using COPY */ + dumpFn = dumpTableData_copy; + + /* + * When load-via-partition-root is set, get the root table name for + * the partition table, so that we can reload data through the root + * table. + */ + if (dopt->load_via_partition_root && tbinfo->ispartition) + { + TableInfo *parentTbinfo; + + parentTbinfo = getRootTableInfo(tbinfo); + copyFrom = fmtQualifiedDumpable(parentTbinfo); + } + else + copyFrom = fmtQualifiedDumpable(tbinfo); + + /* must use 2 steps here 'cause fmtId is nonreentrant */ + appendPQExpBuffer(copyBuf, "COPY %s ", + copyFrom); + appendPQExpBuffer(copyBuf, "%s FROM stdin;\n", + fmtCopyColumnList(tbinfo, clistBuf)); + copyStmt = copyBuf->data; + } + else + { + /* Restore using INSERT */ + dumpFn = dumpTableData_insert; + copyStmt = NULL; + } + + /* + * Note: although the TableDataInfo is a full DumpableObject, we treat its + * dependency on its table as "special" and pass it to ArchiveEntry now. + * See comments for BuildArchiveDependencies. + */ + if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) + { + TocEntry *te; + + te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "TABLE DATA", + .section = SECTION_DATA, + .copyStmt = copyStmt, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1, + .dumpFn = dumpFn, + .dumpArg = tdinfo)); + + /* + * Set the TocEntry's dataLength in case we are doing a parallel dump + * and want to order dump jobs by table size. We choose to measure + * dataLength in table pages during dump, so no scaling is needed. + * However, relpages is declared as "integer" in pg_class, and hence + * also in TableInfo, but it's really BlockNumber a/k/a unsigned int. + * Cast so that we get the right interpretation of table sizes + * exceeding INT_MAX pages. + */ + te->dataLength = (BlockNumber) tbinfo->relpages; + } + + destroyPQExpBuffer(copyBuf); + destroyPQExpBuffer(clistBuf); +} + +/* + * refreshMatViewData - + * load or refresh the contents of a single materialized view + * + * Actually, this just makes an ArchiveEntry for the REFRESH MATERIALIZED VIEW + * statement. + */ +static void +refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo) +{ + TableInfo *tbinfo = tdinfo->tdtable; + PQExpBuffer q; + + /* If the materialized view is not flagged as populated, skip this. */ + if (!tbinfo->relispopulated) + return; + + q = createPQExpBuffer(); + + appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n", + fmtQualifiedDumpable(tbinfo)); + + if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) + ArchiveEntry(fout, + tdinfo->dobj.catId, /* catalog ID */ + tdinfo->dobj.dumpId, /* dump ID */ + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "MATERIALIZED VIEW DATA", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .deps = tdinfo->dobj.dependencies, + .nDeps = tdinfo->dobj.nDeps)); + + destroyPQExpBuffer(q); +} + +/* + * getTableData - + * set up dumpable objects representing the contents of tables + */ +static void +getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind) +{ + int i; + + for (i = 0; i < numTables; i++) + { + if (tblinfo[i].dobj.dump & DUMP_COMPONENT_DATA && + (!relkind || tblinfo[i].relkind == relkind)) + makeTableDataInfo(dopt, &(tblinfo[i])); + } +} + +/* + * Make a dumpable object for the data of this specific table + * + * Note: we make a TableDataInfo if and only if we are going to dump the + * table data; the "dump" flag in such objects isn't used. + */ +static void +makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo) +{ + TableDataInfo *tdinfo; + + /* + * Nothing to do if we already decided to dump the table. This will + * happen for "config" tables. + */ + if (tbinfo->dataObj != NULL) + return; + + /* Skip VIEWs (no data to dump) */ + if (tbinfo->relkind == RELKIND_VIEW) + return; + /* Skip FOREIGN TABLEs (no data to dump) unless requested explicitly */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && + (foreign_servers_include_oids.head == NULL || + !simple_oid_list_member(&foreign_servers_include_oids, + tbinfo->foreign_server))) + return; + /* Skip partitioned tables (data in partitions) */ + if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE) + return; + + /* Don't dump data in unlogged tables, if so requested */ + if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED && + dopt->no_unlogged_table_data) + return; + + /* Check that the data is not explicitly excluded */ + if (simple_oid_list_member(&tabledata_exclude_oids, + tbinfo->dobj.catId.oid)) + return; + + /* OK, let's dump it */ + tdinfo = (TableDataInfo *) pg_malloc(sizeof(TableDataInfo)); + + if (tbinfo->relkind == RELKIND_MATVIEW) + tdinfo->dobj.objType = DO_REFRESH_MATVIEW; + else if (tbinfo->relkind == RELKIND_SEQUENCE) + tdinfo->dobj.objType = DO_SEQUENCE_SET; + else + tdinfo->dobj.objType = DO_TABLE_DATA; + + /* + * Note: use tableoid 0 so that this object won't be mistaken for + * something that pg_depend entries apply to. + */ + tdinfo->dobj.catId.tableoid = 0; + tdinfo->dobj.catId.oid = tbinfo->dobj.catId.oid; + AssignDumpId(&tdinfo->dobj); + tdinfo->dobj.name = tbinfo->dobj.name; + tdinfo->dobj.namespace = tbinfo->dobj.namespace; + tdinfo->tdtable = tbinfo; + tdinfo->filtercond = NULL; /* might get set later */ + addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId); + + tbinfo->dataObj = tdinfo; + + /* Make sure that we'll collect per-column info for this table. */ + tbinfo->interesting = true; +} + +/* + * The refresh for a materialized view must be dependent on the refresh for + * any materialized view that this one is dependent on. + * + * This must be called after all the objects are created, but before they are + * sorted. + */ +static void +buildMatViewRefreshDependencies(Archive *fout) +{ + PQExpBuffer query; + PGresult *res; + int ntups, + i; + int i_classid, + i_objid, + i_refobjid; + + /* No Mat Views before 9.3. */ + if (fout->remoteVersion < 90300) + return; + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "WITH RECURSIVE w AS " + "( " + "SELECT d1.objid, d2.refobjid, c2.relkind AS refrelkind " + "FROM pg_depend d1 " + "JOIN pg_class c1 ON c1.oid = d1.objid " + "AND c1.relkind = " CppAsString2(RELKIND_MATVIEW) + " JOIN pg_rewrite r1 ON r1.ev_class = d1.objid " + "JOIN pg_depend d2 ON d2.classid = 'pg_rewrite'::regclass " + "AND d2.objid = r1.oid " + "AND d2.refobjid <> d1.objid " + "JOIN pg_class c2 ON c2.oid = d2.refobjid " + "AND c2.relkind IN (" CppAsString2(RELKIND_MATVIEW) "," + CppAsString2(RELKIND_VIEW) ") " + "WHERE d1.classid = 'pg_class'::regclass " + "UNION " + "SELECT w.objid, d3.refobjid, c3.relkind " + "FROM w " + "JOIN pg_rewrite r3 ON r3.ev_class = w.refobjid " + "JOIN pg_depend d3 ON d3.classid = 'pg_rewrite'::regclass " + "AND d3.objid = r3.oid " + "AND d3.refobjid <> w.refobjid " + "JOIN pg_class c3 ON c3.oid = d3.refobjid " + "AND c3.relkind IN (" CppAsString2(RELKIND_MATVIEW) "," + CppAsString2(RELKIND_VIEW) ") " + ") " + "SELECT 'pg_class'::regclass::oid AS classid, objid, refobjid " + "FROM w " + "WHERE refrelkind = " CppAsString2(RELKIND_MATVIEW)); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_classid = PQfnumber(res, "classid"); + i_objid = PQfnumber(res, "objid"); + i_refobjid = PQfnumber(res, "refobjid"); + + for (i = 0; i < ntups; i++) + { + CatalogId objId; + CatalogId refobjId; + DumpableObject *dobj; + DumpableObject *refdobj; + TableInfo *tbinfo; + TableInfo *reftbinfo; + + objId.tableoid = atooid(PQgetvalue(res, i, i_classid)); + objId.oid = atooid(PQgetvalue(res, i, i_objid)); + refobjId.tableoid = objId.tableoid; + refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid)); + + dobj = findObjectByCatalogId(objId); + if (dobj == NULL) + continue; + + Assert(dobj->objType == DO_TABLE); + tbinfo = (TableInfo *) dobj; + Assert(tbinfo->relkind == RELKIND_MATVIEW); + dobj = (DumpableObject *) tbinfo->dataObj; + if (dobj == NULL) + continue; + Assert(dobj->objType == DO_REFRESH_MATVIEW); + + refdobj = findObjectByCatalogId(refobjId); + if (refdobj == NULL) + continue; + + Assert(refdobj->objType == DO_TABLE); + reftbinfo = (TableInfo *) refdobj; + Assert(reftbinfo->relkind == RELKIND_MATVIEW); + refdobj = (DumpableObject *) reftbinfo->dataObj; + if (refdobj == NULL) + continue; + Assert(refdobj->objType == DO_REFRESH_MATVIEW); + + addObjectDependency(dobj, refdobj->dumpId); + + if (!reftbinfo->relispopulated) + tbinfo->relispopulated = false; + } + + PQclear(res); + + destroyPQExpBuffer(query); +} + +/* + * getTableDataFKConstraints - + * add dump-order dependencies reflecting foreign key constraints + * + * This code is executed only in a data-only dump --- in schema+data dumps + * we handle foreign key issues by not creating the FK constraints until + * after the data is loaded. In a data-only dump, however, we want to + * order the table data objects in such a way that a table's referenced + * tables are restored first. (In the presence of circular references or + * self-references this may be impossible; we'll detect and complain about + * that during the dependency sorting step.) + */ +static void +getTableDataFKConstraints(void) +{ + DumpableObject **dobjs; + int numObjs; + int i; + + /* Search through all the dumpable objects for FK constraints */ + getDumpableObjects(&dobjs, &numObjs); + for (i = 0; i < numObjs; i++) + { + if (dobjs[i]->objType == DO_FK_CONSTRAINT) + { + ConstraintInfo *cinfo = (ConstraintInfo *) dobjs[i]; + TableInfo *ftable; + + /* Not interesting unless both tables are to be dumped */ + if (cinfo->contable == NULL || + cinfo->contable->dataObj == NULL) + continue; + ftable = findTableByOid(cinfo->confrelid); + if (ftable == NULL || + ftable->dataObj == NULL) + continue; + + /* + * Okay, make referencing table's TABLE_DATA object depend on the + * referenced table's TABLE_DATA object. + */ + addObjectDependency(&cinfo->contable->dataObj->dobj, + ftable->dataObj->dobj.dumpId); + } + } + free(dobjs); +} + + +/* + * guessConstraintInheritance: + * In pre-8.4 databases, we can't tell for certain which constraints + * are inherited. We assume a CHECK constraint is inherited if its name + * matches the name of any constraint in the parent. Originally this code + * tried to compare the expression texts, but that can fail for various + * reasons --- for example, if the parent and child tables are in different + * schemas, reverse-listing of function calls may produce different text + * (schema-qualified or not) depending on search path. + * + * In 8.4 and up we can rely on the conislocal field to decide which + * constraints must be dumped; much safer. + * + * This function assumes all conislocal flags were initialized to true. + * It clears the flag on anything that seems to be inherited. + */ +static void +guessConstraintInheritance(TableInfo *tblinfo, int numTables) +{ + int i, + j, + k; + + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &(tblinfo[i]); + int numParents; + TableInfo **parents; + TableInfo *parent; + + /* Sequences and views never have parents */ + if (tbinfo->relkind == RELKIND_SEQUENCE || + tbinfo->relkind == RELKIND_VIEW) + continue; + + /* Don't bother computing anything for non-target tables, either */ + if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + continue; + + numParents = tbinfo->numParents; + parents = tbinfo->parents; + + if (numParents == 0) + continue; /* nothing to see here, move along */ + + /* scan for inherited CHECK constraints */ + for (j = 0; j < tbinfo->ncheck; j++) + { + ConstraintInfo *constr; + + constr = &(tbinfo->checkexprs[j]); + + for (k = 0; k < numParents; k++) + { + int l; + + parent = parents[k]; + for (l = 0; l < parent->ncheck; l++) + { + ConstraintInfo *pconstr = &(parent->checkexprs[l]); + + if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0) + { + constr->conislocal = false; + break; + } + } + if (!constr->conislocal) + break; + } + } + } +} + + +/* + * dumpDatabase: + * dump the database definition + */ +static void +dumpDatabase(Archive *fout) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer dbQry = createPQExpBuffer(); + PQExpBuffer delQry = createPQExpBuffer(); + PQExpBuffer creaQry = createPQExpBuffer(); + PQExpBuffer labelq = createPQExpBuffer(); + PGconn *conn = GetConnection(fout); + PGresult *res; + int i_tableoid, + i_oid, + i_datname, + i_dba, + i_encoding, + i_collate, + i_ctype, + i_frozenxid, + i_minmxid, + i_datacl, + i_rdatacl, + i_datistemplate, + i_datconnlimit, + i_tablespace; + CatalogId dbCatId; + DumpId dbDumpId; + const char *datname, + *dba, + *encoding, + *collate, + *ctype, + *datacl, + *rdatacl, + *datistemplate, + *datconnlimit, + *tablespace; + uint32 frozenxid, + minmxid; + char *qdatname; + + pg_log_info("saving database definition"); + + /* + * Fetch the database-level properties for this database. + * + * The order in which privileges are in the ACL string (the order they + * have been GRANT'd in, which the backend maintains) must be preserved to + * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on + * those are dumped in the correct order. Note that initial privileges + * (pg_init_privs) are not supported on databases, so this logic cannot + * make use of buildACLQueries(). + */ + if (fout->remoteVersion >= 90600) + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "datcollate, datctype, datfrozenxid, datminmxid, " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(coalesce(datacl,acldefault('d',datdba))) " + " WITH ORDINALITY AS perm(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(acldefault('d',datdba)) " + " AS init(init_acl) " + " WHERE acl = init_acl)) AS datacls) " + " AS datacl, " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(acldefault('d',datdba)) " + " WITH ORDINALITY AS initp(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(coalesce(datacl,acldefault('d',datdba))) " + " AS permp(orig_acl) " + " WHERE acl = orig_acl)) AS rdatacls) " + " AS rdatacl, " + "datistemplate, datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " + "shobj_description(oid, 'pg_database') AS description " + + "FROM pg_database " + "WHERE datname = current_database()", + username_subquery); + } + else if (fout->remoteVersion >= 90300) + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "datcollate, datctype, datfrozenxid, datminmxid, " + "datacl, '' as rdatacl, datistemplate, datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " + "shobj_description(oid, 'pg_database') AS description " + + "FROM pg_database " + "WHERE datname = current_database()", + username_subquery); + } + else if (fout->remoteVersion >= 80400) + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "datcollate, datctype, datfrozenxid, 0 AS datminmxid, " + "datacl, '' as rdatacl, datistemplate, datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " + "shobj_description(oid, 'pg_database') AS description " + + "FROM pg_database " + "WHERE datname = current_database()", + username_subquery); + } + else if (fout->remoteVersion >= 80200) + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, " + "datacl, '' as rdatacl, datistemplate, datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " + "shobj_description(oid, 'pg_database') AS description " + + "FROM pg_database " + "WHERE datname = current_database()", + username_subquery); + } + else + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, " + "datacl, '' as rdatacl, datistemplate, " + "-1 as datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace " + "FROM pg_database " + "WHERE datname = current_database()", + username_subquery); + } + + res = ExecuteSqlQueryForSingleRow(fout, dbQry->data); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_datname = PQfnumber(res, "datname"); + i_dba = PQfnumber(res, "dba"); + i_encoding = PQfnumber(res, "encoding"); + i_collate = PQfnumber(res, "datcollate"); + i_ctype = PQfnumber(res, "datctype"); + i_frozenxid = PQfnumber(res, "datfrozenxid"); + i_minmxid = PQfnumber(res, "datminmxid"); + i_datacl = PQfnumber(res, "datacl"); + i_rdatacl = PQfnumber(res, "rdatacl"); + i_datistemplate = PQfnumber(res, "datistemplate"); + i_datconnlimit = PQfnumber(res, "datconnlimit"); + i_tablespace = PQfnumber(res, "tablespace"); + + dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid)); + dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid)); + datname = PQgetvalue(res, 0, i_datname); + dba = PQgetvalue(res, 0, i_dba); + encoding = PQgetvalue(res, 0, i_encoding); + collate = PQgetvalue(res, 0, i_collate); + ctype = PQgetvalue(res, 0, i_ctype); + frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid)); + minmxid = atooid(PQgetvalue(res, 0, i_minmxid)); + datacl = PQgetvalue(res, 0, i_datacl); + rdatacl = PQgetvalue(res, 0, i_rdatacl); + datistemplate = PQgetvalue(res, 0, i_datistemplate); + datconnlimit = PQgetvalue(res, 0, i_datconnlimit); + tablespace = PQgetvalue(res, 0, i_tablespace); + + qdatname = pg_strdup(fmtId(datname)); + + /* + * Prepare the CREATE DATABASE command. We must specify encoding, locale, + * and tablespace since those can't be altered later. Other DB properties + * are left to the DATABASE PROPERTIES entry, so that they can be applied + * after reconnecting to the target DB. + */ + appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", + qdatname); + if (strlen(encoding) > 0) + { + appendPQExpBufferStr(creaQry, " ENCODING = "); + appendStringLiteralAH(creaQry, encoding, fout); + } + if (strlen(collate) > 0 && strcmp(collate, ctype) == 0) + { + appendPQExpBufferStr(creaQry, " LOCALE = "); + appendStringLiteralAH(creaQry, collate, fout); + } + else + { + if (strlen(collate) > 0) + { + appendPQExpBufferStr(creaQry, " LC_COLLATE = "); + appendStringLiteralAH(creaQry, collate, fout); + } + if (strlen(ctype) > 0) + { + appendPQExpBufferStr(creaQry, " LC_CTYPE = "); + appendStringLiteralAH(creaQry, ctype, fout); + } + } + + /* + * Note: looking at dopt->outputNoTablespaces here is completely the wrong + * thing; the decision whether to specify a tablespace should be left till + * pg_restore, so that pg_restore --no-tablespaces applies. Ideally we'd + * label the DATABASE entry with the tablespace and let the normal + * tablespace selection logic work ... but CREATE DATABASE doesn't pay + * attention to default_tablespace, so that won't work. + */ + if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0 && + !dopt->outputNoTablespaces) + appendPQExpBuffer(creaQry, " TABLESPACE = %s", + fmtId(tablespace)); + appendPQExpBufferStr(creaQry, ";\n"); + + appendPQExpBuffer(delQry, "DROP DATABASE %s;\n", + qdatname); + + dbDumpId = createDumpId(); + + ArchiveEntry(fout, + dbCatId, /* catalog ID */ + dbDumpId, /* dump ID */ + ARCHIVE_OPTS(.tag = datname, + .owner = dba, + .description = "DATABASE", + .section = SECTION_PRE_DATA, + .createStmt = creaQry->data, + .dropStmt = delQry->data)); + + /* Compute correct tag for archive entry */ + appendPQExpBuffer(labelq, "DATABASE %s", qdatname); + + /* Dump DB comment if any */ + if (fout->remoteVersion >= 80200) + { + /* + * 8.2 and up keep comments on shared objects in a shared table, so we + * cannot use the dumpComment() code used for other database objects. + * Be careful that the ArchiveEntry parameters match that function. + */ + char *comment = PQgetvalue(res, 0, PQfnumber(res, "description")); + + if (comment && *comment && !dopt->no_comments) + { + resetPQExpBuffer(dbQry); + + /* + * Generates warning when loaded into a differently-named + * database. + */ + appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", qdatname); + appendStringLiteralAH(dbQry, comment, fout); + appendPQExpBufferStr(dbQry, ";\n"); + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = labelq->data, + .owner = dba, + .description = "COMMENT", + .section = SECTION_NONE, + .createStmt = dbQry->data, + .deps = &dbDumpId, + .nDeps = 1)); + } + } + else + { + dumpComment(fout, "DATABASE", qdatname, NULL, dba, + dbCatId, 0, dbDumpId); + } + + /* Dump DB security label, if enabled */ + if (!dopt->no_security_labels && fout->remoteVersion >= 90200) + { + PGresult *shres; + PQExpBuffer seclabelQry; + + seclabelQry = createPQExpBuffer(); + + buildShSecLabelQuery("pg_database", dbCatId.oid, seclabelQry); + shres = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK); + resetPQExpBuffer(seclabelQry); + emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname); + if (seclabelQry->len > 0) + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = labelq->data, + .owner = dba, + .description = "SECURITY LABEL", + .section = SECTION_NONE, + .createStmt = seclabelQry->data, + .deps = &dbDumpId, + .nDeps = 1)); + destroyPQExpBuffer(seclabelQry); + PQclear(shres); + } + + /* + * Dump ACL if any. Note that we do not support initial privileges + * (pg_init_privs) on databases. + */ + dumpACL(fout, dbDumpId, InvalidDumpId, "DATABASE", + qdatname, NULL, NULL, + dba, datacl, rdatacl, "", ""); + + /* + * Now construct a DATABASE PROPERTIES archive entry to restore any + * non-default database-level properties. (The reason this must be + * separate is that we cannot put any additional commands into the TOC + * entry that has CREATE DATABASE. pg_restore would execute such a group + * in an implicit transaction block, and the backend won't allow CREATE + * DATABASE in that context.) + */ + resetPQExpBuffer(creaQry); + resetPQExpBuffer(delQry); + + if (strlen(datconnlimit) > 0 && strcmp(datconnlimit, "-1") != 0) + appendPQExpBuffer(creaQry, "ALTER DATABASE %s CONNECTION LIMIT = %s;\n", + qdatname, datconnlimit); + + if (strcmp(datistemplate, "t") == 0) + { + appendPQExpBuffer(creaQry, "ALTER DATABASE %s IS_TEMPLATE = true;\n", + qdatname); + + /* + * The backend won't accept DROP DATABASE on a template database. We + * can deal with that by removing the template marking before the DROP + * gets issued. We'd prefer to use ALTER DATABASE IF EXISTS here, but + * since no such command is currently supported, fake it with a direct + * UPDATE on pg_database. + */ + appendPQExpBufferStr(delQry, "UPDATE pg_catalog.pg_database " + "SET datistemplate = false WHERE datname = "); + appendStringLiteralAH(delQry, datname, fout); + appendPQExpBufferStr(delQry, ";\n"); + } + + /* Add database-specific SET options */ + dumpDatabaseConfig(fout, creaQry, datname, dbCatId.oid); + + /* + * We stick this binary-upgrade query into the DATABASE PROPERTIES archive + * entry, too, for lack of a better place. + */ + if (dopt->binary_upgrade) + { + appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid and datminmxid.\n"); + appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n" + "SET datfrozenxid = '%u', datminmxid = '%u'\n" + "WHERE datname = ", + frozenxid, minmxid); + appendStringLiteralAH(creaQry, datname, fout); + appendPQExpBufferStr(creaQry, ";\n"); + } + + if (creaQry->len > 0) + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = datname, + .owner = dba, + .description = "DATABASE PROPERTIES", + .section = SECTION_PRE_DATA, + .createStmt = creaQry->data, + .dropStmt = delQry->data, + .deps = &dbDumpId)); + + /* + * pg_largeobject comes from the old system intact, so set its + * relfrozenxids and relminmxids. + */ + if (dopt->binary_upgrade) + { + PGresult *lo_res; + PQExpBuffer loFrozenQry = createPQExpBuffer(); + PQExpBuffer loOutQry = createPQExpBuffer(); + int i_relfrozenxid, + i_relminmxid; + + /* + * pg_largeobject + */ + if (fout->remoteVersion >= 90300) + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid\n" + "FROM pg_catalog.pg_class\n" + "WHERE oid = %u;\n", + LargeObjectRelationId); + else + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid\n" + "FROM pg_catalog.pg_class\n" + "WHERE oid = %u;\n", + LargeObjectRelationId); + + lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data); + + i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid"); + i_relminmxid = PQfnumber(lo_res, "relminmxid"); + + appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid and relminmxid\n"); + appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" + "WHERE oid = %u;\n", + atooid(PQgetvalue(lo_res, 0, i_relfrozenxid)), + atooid(PQgetvalue(lo_res, 0, i_relminmxid)), + LargeObjectRelationId); + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = "pg_largeobject", + .description = "pg_largeobject", + .section = SECTION_PRE_DATA, + .createStmt = loOutQry->data)); + + PQclear(lo_res); + + destroyPQExpBuffer(loFrozenQry); + destroyPQExpBuffer(loOutQry); + } + + PQclear(res); + + free(qdatname); + destroyPQExpBuffer(dbQry); + destroyPQExpBuffer(delQry); + destroyPQExpBuffer(creaQry); + destroyPQExpBuffer(labelq); +} + +/* + * Collect any database-specific or role-and-database-specific SET options + * for this database, and append them to outbuf. + */ +static void +dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf, + const char *dbname, Oid dboid) +{ + PGconn *conn = GetConnection(AH); + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int count = 1; + + /* + * First collect database-specific options. Pre-8.4 server versions lack + * unnest(), so we do this the hard way by querying once per subscript. + */ + for (;;) + { + if (AH->remoteVersion >= 90000) + printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting " + "WHERE setrole = 0 AND setdatabase = '%u'::oid", + count, dboid); + else + printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE oid = '%u'::oid", count, dboid); + + res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK); + + if (PQntuples(res) == 1 && + !PQgetisnull(res, 0, 0)) + { + makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0), + "DATABASE", dbname, NULL, NULL, + outbuf); + PQclear(res); + count++; + } + else + { + PQclear(res); + break; + } + } + + /* Now look for role-and-database-specific options */ + if (AH->remoteVersion >= 90000) + { + /* Here we can assume we have unnest() */ + printfPQExpBuffer(buf, "SELECT rolname, unnest(setconfig) " + "FROM pg_db_role_setting s, pg_roles r " + "WHERE setrole = r.oid AND setdatabase = '%u'::oid", + dboid); + + res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK); + + if (PQntuples(res) > 0) + { + int i; + + for (i = 0; i < PQntuples(res); i++) + makeAlterConfigCommand(conn, PQgetvalue(res, i, 1), + "ROLE", PQgetvalue(res, i, 0), + "DATABASE", dbname, + outbuf); + } + + PQclear(res); + } + + destroyPQExpBuffer(buf); +} + +/* + * dumpEncoding: put the correct encoding into the archive + */ +static void +dumpEncoding(Archive *AH) +{ + const char *encname = pg_encoding_to_char(AH->encoding); + PQExpBuffer qry = createPQExpBuffer(); + + pg_log_info("saving encoding = %s", encname); + + appendPQExpBufferStr(qry, "SET client_encoding = "); + appendStringLiteralAH(qry, encname, AH); + appendPQExpBufferStr(qry, ";\n"); + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = "ENCODING", + .description = "ENCODING", + .section = SECTION_PRE_DATA, + .createStmt = qry->data)); + + destroyPQExpBuffer(qry); +} + + +/* + * dumpStdStrings: put the correct escape string behavior into the archive + */ +static void +dumpStdStrings(Archive *AH) +{ + const char *stdstrings = AH->std_strings ? "on" : "off"; + PQExpBuffer qry = createPQExpBuffer(); + + pg_log_info("saving standard_conforming_strings = %s", + stdstrings); + + appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n", + stdstrings); + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = "STDSTRINGS", + .description = "STDSTRINGS", + .section = SECTION_PRE_DATA, + .createStmt = qry->data)); + + destroyPQExpBuffer(qry); +} + +/* + * dumpSearchPath: record the active search_path in the archive + */ +static void +dumpSearchPath(Archive *AH) +{ + PQExpBuffer qry = createPQExpBuffer(); + PQExpBuffer path = createPQExpBuffer(); + PGresult *res; + char **schemanames = NULL; + int nschemanames = 0; + int i; + + /* + * We use the result of current_schemas(), not the search_path GUC, + * because that might contain wildcards such as "$user", which won't + * necessarily have the same value during restore. Also, this way avoids + * listing schemas that may appear in search_path but not actually exist, + * which seems like a prudent exclusion. + */ + res = ExecuteSqlQueryForSingleRow(AH, + "SELECT pg_catalog.current_schemas(false)"); + + if (!parsePGArray(PQgetvalue(res, 0, 0), &schemanames, &nschemanames)) + fatal("could not parse result of current_schemas()"); + + /* + * We use set_config(), not a simple "SET search_path" command, because + * the latter has less-clean behavior if the search path is empty. While + * that's likely to get fixed at some point, it seems like a good idea to + * be as backwards-compatible as possible in what we put into archives. + */ + for (i = 0; i < nschemanames; i++) + { + if (i > 0) + appendPQExpBufferStr(path, ", "); + appendPQExpBufferStr(path, fmtId(schemanames[i])); + } + + appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', "); + appendStringLiteralAH(qry, path->data, AH); + appendPQExpBufferStr(qry, ", false);\n"); + + pg_log_info("saving search_path = %s", path->data); + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = "SEARCHPATH", + .description = "SEARCHPATH", + .section = SECTION_PRE_DATA, + .createStmt = qry->data)); + + /* Also save it in AH->searchpath, in case we're doing plain text dump */ + AH->searchpath = pg_strdup(qry->data); + + if (schemanames) + free(schemanames); + PQclear(res); + destroyPQExpBuffer(qry); + destroyPQExpBuffer(path); +} + + +/* + * getBlobs: + * Collect schema-level data about large objects + */ +static void +getBlobs(Archive *fout) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer blobQry = createPQExpBuffer(); + BlobInfo *binfo; + DumpableObject *bdata; + PGresult *res; + int ntups; + int i; + int i_oid; + int i_lomowner; + int i_lomacl; + int i_rlomacl; + int i_initlomacl; + int i_initrlomacl; + + pg_log_info("reading large objects"); + + /* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */ + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer init_acl_subquery = createPQExpBuffer(); + PQExpBuffer init_racl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery, + init_racl_subquery, "l.lomacl", "l.lomowner", "'L'", + dopt->binary_upgrade); + + appendPQExpBuffer(blobQry, + "SELECT l.oid, (%s l.lomowner) AS rolname, " + "%s AS lomacl, " + "%s AS rlomacl, " + "%s AS initlomacl, " + "%s AS initrlomacl " + "FROM pg_largeobject_metadata l " + "LEFT JOIN pg_init_privs pip ON " + "(l.oid = pip.objoid " + "AND pip.classoid = 'pg_largeobject'::regclass " + "AND pip.objsubid = 0) ", + username_subquery, + acl_subquery->data, + racl_subquery->data, + init_acl_subquery->data, + init_racl_subquery->data); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(init_acl_subquery); + destroyPQExpBuffer(init_racl_subquery); + } + else if (fout->remoteVersion >= 90000) + appendPQExpBuffer(blobQry, + "SELECT oid, (%s lomowner) AS rolname, lomacl, " + "NULL AS rlomacl, NULL AS initlomacl, " + "NULL AS initrlomacl " + " FROM pg_largeobject_metadata", + username_subquery); + else + appendPQExpBufferStr(blobQry, + "SELECT DISTINCT loid AS oid, " + "NULL::name AS rolname, NULL::oid AS lomacl, " + "NULL::oid AS rlomacl, NULL::oid AS initlomacl, " + "NULL::oid AS initrlomacl " + " FROM pg_largeobject"); + + res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK); + + i_oid = PQfnumber(res, "oid"); + i_lomowner = PQfnumber(res, "rolname"); + i_lomacl = PQfnumber(res, "lomacl"); + i_rlomacl = PQfnumber(res, "rlomacl"); + i_initlomacl = PQfnumber(res, "initlomacl"); + i_initrlomacl = PQfnumber(res, "initrlomacl"); + + ntups = PQntuples(res); + + /* + * Each large object has its own BLOB archive entry. + */ + binfo = (BlobInfo *) pg_malloc(ntups * sizeof(BlobInfo)); + + for (i = 0; i < ntups; i++) + { + binfo[i].dobj.objType = DO_BLOB; + binfo[i].dobj.catId.tableoid = LargeObjectRelationId; + binfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&binfo[i].dobj); + + binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oid)); + binfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_lomowner)); + binfo[i].blobacl = pg_strdup(PQgetvalue(res, i, i_lomacl)); + binfo[i].rblobacl = pg_strdup(PQgetvalue(res, i, i_rlomacl)); + binfo[i].initblobacl = pg_strdup(PQgetvalue(res, i, i_initlomacl)); + binfo[i].initrblobacl = pg_strdup(PQgetvalue(res, i, i_initrlomacl)); + + if (PQgetisnull(res, i, i_lomacl) && + PQgetisnull(res, i, i_rlomacl) && + PQgetisnull(res, i, i_initlomacl) && + PQgetisnull(res, i, i_initrlomacl)) + binfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + /* + * In binary-upgrade mode for blobs, we do *not* dump out the blob + * data, as it will be copied by pg_upgrade, which simply copies the + * pg_largeobject table. We *do* however dump out anything but the + * data, as pg_upgrade copies just pg_largeobject, but not + * pg_largeobject_metadata, after the dump is restored. + */ + if (dopt->binary_upgrade) + binfo[i].dobj.dump &= ~DUMP_COMPONENT_DATA; + } + + /* + * If we have any large objects, a "BLOBS" archive entry is needed. This + * is just a placeholder for sorting; it carries no data now. + */ + if (ntups > 0) + { + bdata = (DumpableObject *) pg_malloc(sizeof(DumpableObject)); + bdata->objType = DO_BLOB_DATA; + bdata->catId = nilCatalogId; + AssignDumpId(bdata); + bdata->name = pg_strdup("BLOBS"); + } + + PQclear(res); + destroyPQExpBuffer(blobQry); +} + +/* + * dumpBlob + * + * dump the definition (metadata) of the given large object + */ +static void +dumpBlob(Archive *fout, const BlobInfo *binfo) +{ + PQExpBuffer cquery = createPQExpBuffer(); + PQExpBuffer dquery = createPQExpBuffer(); + + appendPQExpBuffer(cquery, + "SELECT pg_catalog.lo_create('%s');\n", + binfo->dobj.name); + + appendPQExpBuffer(dquery, + "SELECT pg_catalog.lo_unlink('%s');\n", + binfo->dobj.name); + + if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = binfo->dobj.name, + .owner = binfo->rolname, + .description = "BLOB", + .section = SECTION_PRE_DATA, + .createStmt = cquery->data, + .dropStmt = dquery->data)); + + /* Dump comment if any */ + if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "LARGE OBJECT", binfo->dobj.name, + NULL, binfo->rolname, + binfo->dobj.catId, 0, binfo->dobj.dumpId); + + /* Dump security label if any */ + if (binfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "LARGE OBJECT", binfo->dobj.name, + NULL, binfo->rolname, + binfo->dobj.catId, 0, binfo->dobj.dumpId); + + /* Dump ACL if any */ + if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL)) + dumpACL(fout, binfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT", + binfo->dobj.name, NULL, + NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl, + binfo->initblobacl, binfo->initrblobacl); + + destroyPQExpBuffer(cquery); + destroyPQExpBuffer(dquery); +} + +/* + * dumpBlobs: + * dump the data contents of all large objects + */ +static int +dumpBlobs(Archive *fout, const void *arg) +{ + const char *blobQry; + const char *blobFetchQry; + PGconn *conn = GetConnection(fout); + PGresult *res; + char buf[LOBBUFSIZE]; + int ntups; + int i; + int cnt; + + pg_log_info("saving large objects"); + + /* + * Currently, we re-fetch all BLOB OIDs using a cursor. Consider scanning + * the already-in-memory dumpable objects instead... + */ + if (fout->remoteVersion >= 90000) + blobQry = + "DECLARE bloboid CURSOR FOR " + "SELECT oid FROM pg_largeobject_metadata ORDER BY 1"; + else + blobQry = + "DECLARE bloboid CURSOR FOR " + "SELECT DISTINCT loid FROM pg_largeobject ORDER BY 1"; + + ExecuteSqlStatement(fout, blobQry); + + /* Command to fetch from cursor */ + blobFetchQry = "FETCH 1000 IN bloboid"; + + do + { + /* Do a fetch */ + res = ExecuteSqlQuery(fout, blobFetchQry, PGRES_TUPLES_OK); + + /* Process the tuples, if any */ + ntups = PQntuples(res); + for (i = 0; i < ntups; i++) + { + Oid blobOid; + int loFd; + + blobOid = atooid(PQgetvalue(res, i, 0)); + /* Open the BLOB */ + loFd = lo_open(conn, blobOid, INV_READ); + if (loFd == -1) + fatal("could not open large object %u: %s", + blobOid, PQerrorMessage(conn)); + + StartBlob(fout, blobOid); + + /* Now read it in chunks, sending data to archive */ + do + { + cnt = lo_read(conn, loFd, buf, LOBBUFSIZE); + if (cnt < 0) + fatal("error reading large object %u: %s", + blobOid, PQerrorMessage(conn)); + + WriteData(fout, buf, cnt); + } while (cnt > 0); + + lo_close(conn, loFd); + + EndBlob(fout, blobOid); + } + + PQclear(res); + } while (ntups > 0); + + return 1; +} + +/* + * getPolicies + * get information about all RLS policies on dumpable tables. + */ +void +getPolicies(Archive *fout, TableInfo tblinfo[], int numTables) +{ + PQExpBuffer query; + PGresult *res; + PolicyInfo *polinfo; + int i_oid; + int i_tableoid; + int i_polrelid; + int i_polname; + int i_polcmd; + int i_polpermissive; + int i_polroles; + int i_polqual; + int i_polwithcheck; + int i, + j, + ntups; + + if (fout->remoteVersion < 90500) + return; + + query = createPQExpBuffer(); + + /* + * First, check which tables have RLS enabled. We represent RLS being + * enabled on a table by creating a PolicyInfo object with null polname. + */ + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &tblinfo[i]; + + /* Ignore row security on tables not to be dumped */ + if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY)) + continue; + + if (tbinfo->rowsec) + { + /* + * Note: use tableoid 0 so that this object won't be mistaken for + * something that pg_depend entries apply to. + */ + polinfo = pg_malloc(sizeof(PolicyInfo)); + polinfo->dobj.objType = DO_POLICY; + polinfo->dobj.catId.tableoid = 0; + polinfo->dobj.catId.oid = tbinfo->dobj.catId.oid; + AssignDumpId(&polinfo->dobj); + polinfo->dobj.namespace = tbinfo->dobj.namespace; + polinfo->dobj.name = pg_strdup(tbinfo->dobj.name); + polinfo->poltable = tbinfo; + polinfo->polname = NULL; + polinfo->polcmd = '\0'; + polinfo->polpermissive = 0; + polinfo->polroles = NULL; + polinfo->polqual = NULL; + polinfo->polwithcheck = NULL; + } + } + + /* + * Now, read all RLS policies, and create PolicyInfo objects for all those + * that are of interest. + */ + pg_log_info("reading row-level security policies"); + + printfPQExpBuffer(query, + "SELECT oid, tableoid, pol.polrelid, pol.polname, pol.polcmd, "); + if (fout->remoteVersion >= 100000) + appendPQExpBuffer(query, "pol.polpermissive, "); + else + appendPQExpBuffer(query, "'t' as polpermissive, "); + appendPQExpBuffer(query, + "CASE WHEN pol.polroles = '{0}' THEN NULL ELSE " + " pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(rolname) from pg_catalog.pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, " + "pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS polqual, " + "pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck " + "FROM pg_catalog.pg_policy pol"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + if (ntups > 0) + { + i_oid = PQfnumber(res, "oid"); + i_tableoid = PQfnumber(res, "tableoid"); + i_polrelid = PQfnumber(res, "polrelid"); + i_polname = PQfnumber(res, "polname"); + i_polcmd = PQfnumber(res, "polcmd"); + i_polpermissive = PQfnumber(res, "polpermissive"); + i_polroles = PQfnumber(res, "polroles"); + i_polqual = PQfnumber(res, "polqual"); + i_polwithcheck = PQfnumber(res, "polwithcheck"); + + polinfo = pg_malloc(ntups * sizeof(PolicyInfo)); + + for (j = 0; j < ntups; j++) + { + Oid polrelid = atooid(PQgetvalue(res, j, i_polrelid)); + TableInfo *tbinfo = findTableByOid(polrelid); + + /* + * Ignore row security on tables not to be dumped. (This will + * result in some harmless wasted slots in polinfo[].) + */ + if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY)) + continue; + + polinfo[j].dobj.objType = DO_POLICY; + polinfo[j].dobj.catId.tableoid = + atooid(PQgetvalue(res, j, i_tableoid)); + polinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); + AssignDumpId(&polinfo[j].dobj); + polinfo[j].dobj.namespace = tbinfo->dobj.namespace; + polinfo[j].poltable = tbinfo; + polinfo[j].polname = pg_strdup(PQgetvalue(res, j, i_polname)); + polinfo[j].dobj.name = pg_strdup(polinfo[j].polname); + + polinfo[j].polcmd = *(PQgetvalue(res, j, i_polcmd)); + polinfo[j].polpermissive = *(PQgetvalue(res, j, i_polpermissive)) == 't'; + + if (PQgetisnull(res, j, i_polroles)) + polinfo[j].polroles = NULL; + else + polinfo[j].polroles = pg_strdup(PQgetvalue(res, j, i_polroles)); + + if (PQgetisnull(res, j, i_polqual)) + polinfo[j].polqual = NULL; + else + polinfo[j].polqual = pg_strdup(PQgetvalue(res, j, i_polqual)); + + if (PQgetisnull(res, j, i_polwithcheck)) + polinfo[j].polwithcheck = NULL; + else + polinfo[j].polwithcheck + = pg_strdup(PQgetvalue(res, j, i_polwithcheck)); + } + } + + PQclear(res); + + destroyPQExpBuffer(query); +} + +/* + * dumpPolicy + * dump the definition of the given policy + */ +static void +dumpPolicy(Archive *fout, const PolicyInfo *polinfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = polinfo->poltable; + PQExpBuffer query; + PQExpBuffer delqry; + PQExpBuffer polprefix; + char *qtabname; + const char *cmd; + char *tag; + + if (dopt->dataOnly) + return; + + /* + * If polname is NULL, then this record is just indicating that ROW LEVEL + * SECURITY is enabled for the table. Dump as ALTER TABLE ENABLE + * ROW LEVEL SECURITY. + */ + if (polinfo->polname == NULL) + { + query = createPQExpBuffer(); + + appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;", + fmtQualifiedDumpable(tbinfo)); + + /* + * We must emit the ROW SECURITY object's dependency on its table + * explicitly, because it will not match anything in pg_depend (unlike + * the case for other PolicyInfo objects). + */ + if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY) + ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = polinfo->dobj.name, + .namespace = polinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "ROW SECURITY", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + + destroyPQExpBuffer(query); + return; + } + + if (polinfo->polcmd == '*') + cmd = ""; + else if (polinfo->polcmd == 'r') + cmd = " FOR SELECT"; + else if (polinfo->polcmd == 'a') + cmd = " FOR INSERT"; + else if (polinfo->polcmd == 'w') + cmd = " FOR UPDATE"; + else if (polinfo->polcmd == 'd') + cmd = " FOR DELETE"; + else + { + pg_log_error("unexpected policy command type: %c", + polinfo->polcmd); + exit_nicely(1); + } + + query = createPQExpBuffer(); + delqry = createPQExpBuffer(); + polprefix = createPQExpBuffer(); + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); + + appendPQExpBuffer(query, "CREATE POLICY %s", fmtId(polinfo->polname)); + + appendPQExpBuffer(query, " ON %s%s%s", fmtQualifiedDumpable(tbinfo), + !polinfo->polpermissive ? " AS RESTRICTIVE" : "", cmd); + + if (polinfo->polroles != NULL) + appendPQExpBuffer(query, " TO %s", polinfo->polroles); + + if (polinfo->polqual != NULL) + appendPQExpBuffer(query, " USING (%s)", polinfo->polqual); + + if (polinfo->polwithcheck != NULL) + appendPQExpBuffer(query, " WITH CHECK (%s)", polinfo->polwithcheck); + + appendPQExpBufferStr(query, ";\n"); + + appendPQExpBuffer(delqry, "DROP POLICY %s", fmtId(polinfo->polname)); + appendPQExpBuffer(delqry, " ON %s;\n", fmtQualifiedDumpable(tbinfo)); + + appendPQExpBuffer(polprefix, "POLICY %s ON", + fmtId(polinfo->polname)); + + tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name); + + if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY) + ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = polinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "POLICY", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .dropStmt = delqry->data)); + + if (polinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, polprefix->data, qtabname, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + polinfo->dobj.catId, 0, polinfo->dobj.dumpId); + + free(tag); + destroyPQExpBuffer(query); + destroyPQExpBuffer(delqry); + destroyPQExpBuffer(polprefix); + free(qtabname); +} + +/* + * getPublications + * get information about publications + */ +PublicationInfo * +getPublications(Archive *fout, int *numPublications) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PGresult *res; + PublicationInfo *pubinfo; + int i_tableoid; + int i_oid; + int i_pubname; + int i_rolname; + int i_puballtables; + int i_pubinsert; + int i_pubupdate; + int i_pubdelete; + int i_pubtruncate; + int i_pubviaroot; + int i, + ntups; + + if (dopt->no_publications || fout->remoteVersion < 100000) + { + *numPublications = 0; + return NULL; + } + + query = createPQExpBuffer(); + + resetPQExpBuffer(query); + + /* Get the publications. */ + if (fout->remoteVersion >= 130000) + appendPQExpBuffer(query, + "SELECT p.tableoid, p.oid, p.pubname, " + "(%s p.pubowner) AS rolname, " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot " + "FROM pg_publication p", + username_subquery); + else if (fout->remoteVersion >= 110000) + appendPQExpBuffer(query, + "SELECT p.tableoid, p.oid, p.pubname, " + "(%s p.pubowner) AS rolname, " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot " + "FROM pg_publication p", + username_subquery); + else + appendPQExpBuffer(query, + "SELECT p.tableoid, p.oid, p.pubname, " + "(%s p.pubowner) AS rolname, " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot " + "FROM pg_publication p", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_pubname = PQfnumber(res, "pubname"); + i_rolname = PQfnumber(res, "rolname"); + i_puballtables = PQfnumber(res, "puballtables"); + i_pubinsert = PQfnumber(res, "pubinsert"); + i_pubupdate = PQfnumber(res, "pubupdate"); + i_pubdelete = PQfnumber(res, "pubdelete"); + i_pubtruncate = PQfnumber(res, "pubtruncate"); + i_pubviaroot = PQfnumber(res, "pubviaroot"); + + pubinfo = pg_malloc(ntups * sizeof(PublicationInfo)); + + for (i = 0; i < ntups; i++) + { + pubinfo[i].dobj.objType = DO_PUBLICATION; + pubinfo[i].dobj.catId.tableoid = + atooid(PQgetvalue(res, i, i_tableoid)); + pubinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&pubinfo[i].dobj); + pubinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_pubname)); + pubinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + pubinfo[i].puballtables = + (strcmp(PQgetvalue(res, i, i_puballtables), "t") == 0); + pubinfo[i].pubinsert = + (strcmp(PQgetvalue(res, i, i_pubinsert), "t") == 0); + pubinfo[i].pubupdate = + (strcmp(PQgetvalue(res, i, i_pubupdate), "t") == 0); + pubinfo[i].pubdelete = + (strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0); + pubinfo[i].pubtruncate = + (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0); + pubinfo[i].pubviaroot = + (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0); + + if (strlen(pubinfo[i].rolname) == 0) + pg_log_warning("owner of publication \"%s\" appears to be invalid", + pubinfo[i].dobj.name); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(pubinfo[i].dobj), fout); + } + PQclear(res); + + destroyPQExpBuffer(query); + + *numPublications = ntups; + return pubinfo; +} + +/* + * dumpPublication + * dump the definition of the given publication + */ +static void +dumpPublication(Archive *fout, const PublicationInfo *pubinfo) +{ + PQExpBuffer delq; + PQExpBuffer query; + char *qpubname; + bool first = true; + + if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + return; + + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qpubname = pg_strdup(fmtId(pubinfo->dobj.name)); + + appendPQExpBuffer(delq, "DROP PUBLICATION %s;\n", + qpubname); + + appendPQExpBuffer(query, "CREATE PUBLICATION %s", + qpubname); + + if (pubinfo->puballtables) + appendPQExpBufferStr(query, " FOR ALL TABLES"); + + appendPQExpBufferStr(query, " WITH (publish = '"); + if (pubinfo->pubinsert) + { + appendPQExpBufferStr(query, "insert"); + first = false; + } + + if (pubinfo->pubupdate) + { + if (!first) + appendPQExpBufferStr(query, ", "); + + appendPQExpBufferStr(query, "update"); + first = false; + } + + if (pubinfo->pubdelete) + { + if (!first) + appendPQExpBufferStr(query, ", "); + + appendPQExpBufferStr(query, "delete"); + first = false; + } + + if (pubinfo->pubtruncate) + { + if (!first) + appendPQExpBufferStr(query, ", "); + + appendPQExpBufferStr(query, "truncate"); + first = false; + } + + appendPQExpBufferStr(query, "'"); + + if (pubinfo->pubviaroot) + appendPQExpBufferStr(query, ", publish_via_partition_root = true"); + + appendPQExpBufferStr(query, ");\n"); + + ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = pubinfo->dobj.name, + .owner = pubinfo->rolname, + .description = "PUBLICATION", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .dropStmt = delq->data)); + + if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "PUBLICATION", qpubname, + NULL, pubinfo->rolname, + pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId); + + if (pubinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "PUBLICATION", qpubname, + NULL, pubinfo->rolname, + pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId); + + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qpubname); +} + +/* + * getPublicationTables + * get information about publication membership for dumpable tables. + */ +void +getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) +{ + PQExpBuffer query; + PGresult *res; + PublicationRelInfo *pubrinfo; + DumpOptions *dopt = fout->dopt; + int i_tableoid; + int i_oid; + int i_prpubid; + int i_prrelid; + int i, + j, + ntups; + + if (dopt->no_publications || fout->remoteVersion < 100000) + return; + + query = createPQExpBuffer(); + + /* Collect all publication membership info. */ + appendPQExpBufferStr(query, + "SELECT tableoid, oid, prpubid, prrelid " + "FROM pg_catalog.pg_publication_rel"); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_prpubid = PQfnumber(res, "prpubid"); + i_prrelid = PQfnumber(res, "prrelid"); + + /* this allocation may be more than we need */ + pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo)); + j = 0; + + for (i = 0; i < ntups; i++) + { + Oid prpubid = atooid(PQgetvalue(res, i, i_prpubid)); + Oid prrelid = atooid(PQgetvalue(res, i, i_prrelid)); + PublicationInfo *pubinfo; + TableInfo *tbinfo; + + /* + * Ignore any entries for which we aren't interested in either the + * publication or the rel. + */ + pubinfo = findPublicationByOid(prpubid); + if (pubinfo == NULL) + continue; + tbinfo = findTableByOid(prrelid); + if (tbinfo == NULL) + continue; + + /* + * Ignore publication membership of tables whose definitions are not + * to be dumped. + */ + if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + continue; + + /* OK, make a DumpableObject for this relationship */ + pubrinfo[j].dobj.objType = DO_PUBLICATION_REL; + pubrinfo[j].dobj.catId.tableoid = + atooid(PQgetvalue(res, i, i_tableoid)); + pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&pubrinfo[j].dobj); + pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace; + pubrinfo[j].dobj.name = tbinfo->dobj.name; + pubrinfo[j].publication = pubinfo; + pubrinfo[j].pubtable = tbinfo; + + /* Decide whether we want to dump it */ + selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout); + + j++; + } + + PQclear(res); + destroyPQExpBuffer(query); +} + +/* + * dumpPublicationTable + * dump the definition of the given publication table mapping + */ +static void +dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo) +{ + PublicationInfo *pubinfo = pubrinfo->publication; + TableInfo *tbinfo = pubrinfo->pubtable; + PQExpBuffer query; + char *tag; + + if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + return; + + tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name); + + query = createPQExpBuffer(); + + appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY", + fmtId(pubinfo->dobj.name)); + appendPQExpBuffer(query, " %s;\n", + fmtQualifiedDumpable(tbinfo)); + + /* + * There is no point in creating a drop query as the drop is done by table + * drop. (If you think to change this, see also _printTocEntry().) + * Although this object doesn't really have ownership as such, set the + * owner field anyway to ensure that the command is run by the correct + * role at restore time. + */ + ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = pubinfo->rolname, + .description = "PUBLICATION TABLE", + .section = SECTION_POST_DATA, + .createStmt = query->data)); + + free(tag); + destroyPQExpBuffer(query); +} + +/* + * Is the currently connected user a superuser? + */ +static bool +is_superuser(Archive *fout) +{ + ArchiveHandle *AH = (ArchiveHandle *) fout; + const char *val; + + val = PQparameterStatus(AH->connection, "is_superuser"); + + if (val && strcmp(val, "on") == 0) + return true; + + return false; +} + +/* + * getSubscriptions + * get information about subscriptions + */ +void +getSubscriptions(Archive *fout) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PGresult *res; + SubscriptionInfo *subinfo; + int i_tableoid; + int i_oid; + int i_subname; + int i_rolname; + int i_substream; + int i_subconninfo; + int i_subslotname; + int i_subsynccommit; + int i_subpublications; + int i_subbinary; + int i, + ntups; + + if (dopt->no_subscriptions || fout->remoteVersion < 100000) + return; + + if (!is_superuser(fout)) + { + int n; + + res = ExecuteSqlQuery(fout, + "SELECT count(*) FROM pg_subscription " + "WHERE subdbid = (SELECT oid FROM pg_database" + " WHERE datname = current_database())", + PGRES_TUPLES_OK); + n = atoi(PQgetvalue(res, 0, 0)); + if (n > 0) + pg_log_warning("subscriptions not dumped because current user is not a superuser"); + PQclear(res); + return; + } + + query = createPQExpBuffer(); + + /* Get the subscriptions in current database. */ + appendPQExpBuffer(query, + "SELECT s.tableoid, s.oid, s.subname,\n" + " (%s s.subowner) AS rolname,\n" + " s.subconninfo, s.subslotname, s.subsynccommit,\n" + " s.subpublications,\n", + username_subquery); + + if (fout->remoteVersion >= 140000) + appendPQExpBufferStr(query, " s.subbinary,\n"); + else + appendPQExpBufferStr(query, " false AS subbinary,\n"); + + if (fout->remoteVersion >= 140000) + appendPQExpBufferStr(query, " s.substream\n"); + else + appendPQExpBufferStr(query, " false AS substream\n"); + + appendPQExpBufferStr(query, + "FROM pg_subscription s\n" + "WHERE s.subdbid = (SELECT oid FROM pg_database\n" + " WHERE datname = current_database())"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_subname = PQfnumber(res, "subname"); + i_rolname = PQfnumber(res, "rolname"); + i_subconninfo = PQfnumber(res, "subconninfo"); + i_subslotname = PQfnumber(res, "subslotname"); + i_subsynccommit = PQfnumber(res, "subsynccommit"); + i_subpublications = PQfnumber(res, "subpublications"); + i_subbinary = PQfnumber(res, "subbinary"); + i_substream = PQfnumber(res, "substream"); + + subinfo = pg_malloc(ntups * sizeof(SubscriptionInfo)); + + for (i = 0; i < ntups; i++) + { + subinfo[i].dobj.objType = DO_SUBSCRIPTION; + subinfo[i].dobj.catId.tableoid = + atooid(PQgetvalue(res, i, i_tableoid)); + subinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&subinfo[i].dobj); + subinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_subname)); + subinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + subinfo[i].subconninfo = pg_strdup(PQgetvalue(res, i, i_subconninfo)); + if (PQgetisnull(res, i, i_subslotname)) + subinfo[i].subslotname = NULL; + else + subinfo[i].subslotname = pg_strdup(PQgetvalue(res, i, i_subslotname)); + subinfo[i].subsynccommit = + pg_strdup(PQgetvalue(res, i, i_subsynccommit)); + subinfo[i].subpublications = + pg_strdup(PQgetvalue(res, i, i_subpublications)); + subinfo[i].subbinary = + pg_strdup(PQgetvalue(res, i, i_subbinary)); + subinfo[i].substream = + pg_strdup(PQgetvalue(res, i, i_substream)); + + if (strlen(subinfo[i].rolname) == 0) + pg_log_warning("owner of subscription \"%s\" appears to be invalid", + subinfo[i].dobj.name); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(subinfo[i].dobj), fout); + } + PQclear(res); + + destroyPQExpBuffer(query); +} + +/* + * dumpSubscription + * dump the definition of the given subscription + */ +static void +dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) +{ + PQExpBuffer delq; + PQExpBuffer query; + PQExpBuffer publications; + char *qsubname; + char **pubnames = NULL; + int npubnames = 0; + int i; + + if (!(subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + return; + + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qsubname = pg_strdup(fmtId(subinfo->dobj.name)); + + appendPQExpBuffer(delq, "DROP SUBSCRIPTION %s;\n", + qsubname); + + appendPQExpBuffer(query, "CREATE SUBSCRIPTION %s CONNECTION ", + qsubname); + appendStringLiteralAH(query, subinfo->subconninfo, fout); + + /* Build list of quoted publications and append them to query. */ + if (!parsePGArray(subinfo->subpublications, &pubnames, &npubnames)) + fatal("could not parse subpublications array"); + + publications = createPQExpBuffer(); + for (i = 0; i < npubnames; i++) + { + if (i > 0) + appendPQExpBufferStr(publications, ", "); + + appendPQExpBufferStr(publications, fmtId(pubnames[i])); + } + + appendPQExpBuffer(query, " PUBLICATION %s WITH (connect = false, slot_name = ", publications->data); + if (subinfo->subslotname) + appendStringLiteralAH(query, subinfo->subslotname, fout); + else + appendPQExpBufferStr(query, "NONE"); + + if (strcmp(subinfo->subbinary, "t") == 0) + appendPQExpBufferStr(query, ", binary = true"); + + if (strcmp(subinfo->substream, "f") != 0) + appendPQExpBufferStr(query, ", streaming = on"); + + if (strcmp(subinfo->subsynccommit, "off") != 0) + appendPQExpBuffer(query, ", synchronous_commit = %s", fmtId(subinfo->subsynccommit)); + + appendPQExpBufferStr(query, ");\n"); + + ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = subinfo->dobj.name, + .owner = subinfo->rolname, + .description = "SUBSCRIPTION", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .dropStmt = delq->data)); + + if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "SUBSCRIPTION", qsubname, + NULL, subinfo->rolname, + subinfo->dobj.catId, 0, subinfo->dobj.dumpId); + + if (subinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "SUBSCRIPTION", qsubname, + NULL, subinfo->rolname, + subinfo->dobj.catId, 0, subinfo->dobj.dumpId); + + destroyPQExpBuffer(publications); + if (pubnames) + free(pubnames); + + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qsubname); +} + +/* + * Given a "create query", append as many ALTER ... DEPENDS ON EXTENSION as + * the object needs. + */ +static void +append_depends_on_extension(Archive *fout, + PQExpBuffer create, + const DumpableObject *dobj, + const char *catalog, + const char *keyword, + const char *objname) +{ + if (dobj->depends_on_ext) + { + char *nm; + PGresult *res; + PQExpBuffer query; + int ntups; + int i_extname; + int i; + + /* dodge fmtId() non-reentrancy */ + nm = pg_strdup(objname); + + query = createPQExpBuffer(); + appendPQExpBuffer(query, + "SELECT e.extname " + "FROM pg_catalog.pg_depend d, pg_catalog.pg_extension e " + "WHERE d.refobjid = e.oid AND classid = '%s'::pg_catalog.regclass " + "AND objid = '%u'::pg_catalog.oid AND deptype = 'x' " + "AND refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass", + catalog, + dobj->catId.oid); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + ntups = PQntuples(res); + i_extname = PQfnumber(res, "extname"); + for (i = 0; i < ntups; i++) + { + appendPQExpBuffer(create, "ALTER %s %s DEPENDS ON EXTENSION %s;\n", + keyword, nm, + fmtId(PQgetvalue(res, i, i_extname))); + } + + PQclear(res); + destroyPQExpBuffer(query); + pg_free(nm); + } +} + +static Oid +get_next_possible_free_pg_type_oid(Archive *fout, PQExpBuffer upgrade_query) +{ + /* + * If the old version didn't assign an array type, but the new version + * does, we must select an unused type OID to assign. This currently only + * happens for domains, when upgrading pre-v11 to v11 and up. + * + * Note: local state here is kind of ugly, but we must have some, since we + * mustn't choose the same unused OID more than once. + */ + static Oid next_possible_free_oid = FirstNormalObjectId; + PGresult *res; + bool is_dup; + + do + { + ++next_possible_free_oid; + printfPQExpBuffer(upgrade_query, + "SELECT EXISTS(SELECT 1 " + "FROM pg_catalog.pg_type " + "WHERE oid = '%u'::pg_catalog.oid);", + next_possible_free_oid); + res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); + is_dup = (PQgetvalue(res, 0, 0)[0] == 't'); + PQclear(res); + } while (is_dup); + + return next_possible_free_oid; +} + +static void +binary_upgrade_set_type_oids_by_type_oid(Archive *fout, + PQExpBuffer upgrade_buffer, + Oid pg_type_oid, + bool force_array_type, + bool include_multirange_type) +{ + PQExpBuffer upgrade_query = createPQExpBuffer(); + PGresult *res; + Oid pg_type_array_oid; + Oid pg_type_multirange_oid; + Oid pg_type_multirange_array_oid; + + appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n"); + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n", + pg_type_oid); + + /* we only support old >= 8.3 for binary upgrades */ + appendPQExpBuffer(upgrade_query, + "SELECT typarray " + "FROM pg_catalog.pg_type " + "WHERE oid = '%u'::pg_catalog.oid;", + pg_type_oid); + + res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); + + pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray"))); + + PQclear(res); + + if (!OidIsValid(pg_type_array_oid) && force_array_type) + pg_type_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query); + + if (OidIsValid(pg_type_array_oid)) + { + appendPQExpBufferStr(upgrade_buffer, + "\n-- For binary upgrade, must preserve pg_type array oid\n"); + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_array_pg_type_oid('%u'::pg_catalog.oid);\n\n", + pg_type_array_oid); + } + + /* + * Pre-set the multirange type oid and its own array type oid. + */ + if (include_multirange_type) + { + if (fout->remoteVersion >= 140000) + { + printfPQExpBuffer(upgrade_query, + "SELECT t.oid, t.typarray " + "FROM pg_catalog.pg_type t " + "JOIN pg_catalog.pg_range r " + "ON t.oid = r.rngmultitypid " + "WHERE r.rngtypid = '%u'::pg_catalog.oid;", + pg_type_oid); + + res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); + + pg_type_multirange_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid"))); + pg_type_multirange_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray"))); + + PQclear(res); + } + else + { + pg_type_multirange_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query); + pg_type_multirange_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query); + } + + appendPQExpBufferStr(upgrade_buffer, + "\n-- For binary upgrade, must preserve multirange pg_type oid\n"); + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_multirange_pg_type_oid('%u'::pg_catalog.oid);\n\n", + pg_type_multirange_oid); + appendPQExpBufferStr(upgrade_buffer, + "\n-- For binary upgrade, must preserve multirange pg_type array oid\n"); + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_multirange_array_pg_type_oid('%u'::pg_catalog.oid);\n\n", + pg_type_multirange_array_oid); + } + + destroyPQExpBuffer(upgrade_query); +} + +static void +binary_upgrade_set_type_oids_by_rel_oid(Archive *fout, + PQExpBuffer upgrade_buffer, + Oid pg_rel_oid) +{ + PQExpBuffer upgrade_query = createPQExpBuffer(); + PGresult *upgrade_res; + Oid pg_type_oid; + + appendPQExpBuffer(upgrade_query, + "SELECT c.reltype AS crel " + "FROM pg_catalog.pg_class c " + "WHERE c.oid = '%u'::pg_catalog.oid;", + pg_rel_oid); + + upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); + + pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel"))); + + if (OidIsValid(pg_type_oid)) + binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer, + pg_type_oid, false, false); + + PQclear(upgrade_res); + destroyPQExpBuffer(upgrade_query); +} + +static void +binary_upgrade_set_pg_class_oids(Archive *fout, + PQExpBuffer upgrade_buffer, Oid pg_class_oid, + bool is_index) +{ + appendPQExpBufferStr(upgrade_buffer, + "\n-- For binary upgrade, must preserve pg_class oids\n"); + + if (!is_index) + { + PQExpBuffer upgrade_query = createPQExpBuffer(); + PGresult *upgrade_res; + Oid pg_class_reltoastrelid; + char pg_class_relkind; + Oid pg_index_indexrelid; + + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_heap_pg_class_oid('%u'::pg_catalog.oid);\n", + pg_class_oid); + + /* + * Preserve the OIDs of the table's toast table and index, if any. + * Indexes cannot have toast tables, so we need not make this probe in + * the index code path. + * + * One complexity is that the current table definition might not + * require the creation of a TOAST table, but the old database might + * have a TOAST table that was created earlier, before some wide + * columns were dropped. By setting the TOAST oid we force creation + * of the TOAST heap and index by the new backend, so we can copy the + * files during binary upgrade without worrying about this case. + */ + appendPQExpBuffer(upgrade_query, + "SELECT c.reltoastrelid, c.relkind, i.indexrelid " + "FROM pg_catalog.pg_class c LEFT JOIN " + "pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) " + "WHERE c.oid = '%u'::pg_catalog.oid;", + pg_class_oid); + + upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); + + pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, + PQfnumber(upgrade_res, "reltoastrelid"))); + pg_class_relkind = *PQgetvalue(upgrade_res, 0, + PQfnumber(upgrade_res, "relkind")); + pg_index_indexrelid = atooid(PQgetvalue(upgrade_res, 0, + PQfnumber(upgrade_res, "indexrelid"))); + + /* + * In a pre-v12 database, partitioned tables might be marked as having + * toast tables, but we should ignore them if so. + */ + if (OidIsValid(pg_class_reltoastrelid) && + pg_class_relkind != RELKIND_PARTITIONED_TABLE) + { + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n", + pg_class_reltoastrelid); + + /* every toast table has an index */ + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n", + pg_index_indexrelid); + } + + PQclear(upgrade_res); + destroyPQExpBuffer(upgrade_query); + } + else + appendPQExpBuffer(upgrade_buffer, + "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n", + pg_class_oid); + + appendPQExpBufferChar(upgrade_buffer, '\n'); +} + +/* + * If the DumpableObject is a member of an extension, add a suitable + * ALTER EXTENSION ADD command to the creation commands in upgrade_buffer. + * + * For somewhat historical reasons, objname should already be quoted, + * but not objnamespace (if any). + */ +static void +binary_upgrade_extension_member(PQExpBuffer upgrade_buffer, + const DumpableObject *dobj, + const char *objtype, + const char *objname, + const char *objnamespace) +{ + DumpableObject *extobj = NULL; + int i; + + if (!dobj->ext_member) + return; + + /* + * Find the parent extension. We could avoid this search if we wanted to + * add a link field to DumpableObject, but the space costs of that would + * be considerable. We assume that member objects could only have a + * direct dependency on their own extension, not any others. + */ + for (i = 0; i < dobj->nDeps; i++) + { + extobj = findObjectByDumpId(dobj->dependencies[i]); + if (extobj && extobj->objType == DO_EXTENSION) + break; + extobj = NULL; + } + if (extobj == NULL) + fatal("could not find parent extension for %s %s", + objtype, objname); + + appendPQExpBufferStr(upgrade_buffer, + "\n-- For binary upgrade, handle extension membership the hard way\n"); + appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s ", + fmtId(extobj->name), + objtype); + if (objnamespace && *objnamespace) + appendPQExpBuffer(upgrade_buffer, "%s.", fmtId(objnamespace)); + appendPQExpBuffer(upgrade_buffer, "%s;\n", objname); +} + +/* + * getNamespaces: + * read all namespaces in the system catalogs and return them in the + * NamespaceInfo* structure + * + * numNamespaces is set to the number of namespaces read in + */ +NamespaceInfo * +getNamespaces(Archive *fout, int *numNamespaces) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + NamespaceInfo *nsinfo; + int i_tableoid; + int i_oid; + int i_nspname; + int i_rolname; + int i_nspacl; + int i_rnspacl; + int i_initnspacl; + int i_initrnspacl; + + query = createPQExpBuffer(); + + /* + * we fetch all namespaces including system ones, so that every object we + * read in can be linked to a containing namespace. + */ + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer init_acl_subquery = createPQExpBuffer(); + PQExpBuffer init_racl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, init_acl_subquery, + init_racl_subquery, "n.nspacl", "n.nspowner", "'n'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, "SELECT n.tableoid, n.oid, n.nspname, " + "(%s nspowner) AS rolname, " + "%s as nspacl, " + "%s as rnspacl, " + "%s as initnspacl, " + "%s as initrnspacl " + "FROM pg_namespace n " + "LEFT JOIN pg_init_privs pip " + "ON (n.oid = pip.objoid " + "AND pip.classoid = 'pg_namespace'::regclass " + "AND pip.objsubid = 0", + username_subquery, + acl_subquery->data, + racl_subquery->data, + init_acl_subquery->data, + init_racl_subquery->data); + + appendPQExpBufferStr(query, ") "); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(init_acl_subquery); + destroyPQExpBuffer(init_racl_subquery); + } + else + appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, " + "(%s nspowner) AS rolname, " + "nspacl, NULL as rnspacl, " + "NULL AS initnspacl, NULL as initrnspacl " + "FROM pg_namespace", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + nsinfo = (NamespaceInfo *) pg_malloc(ntups * sizeof(NamespaceInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_nspname = PQfnumber(res, "nspname"); + i_rolname = PQfnumber(res, "rolname"); + i_nspacl = PQfnumber(res, "nspacl"); + i_rnspacl = PQfnumber(res, "rnspacl"); + i_initnspacl = PQfnumber(res, "initnspacl"); + i_initrnspacl = PQfnumber(res, "initrnspacl"); + + for (i = 0; i < ntups; i++) + { + nsinfo[i].dobj.objType = DO_NAMESPACE; + nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&nsinfo[i].dobj); + nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname)); + nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl)); + nsinfo[i].rnspacl = pg_strdup(PQgetvalue(res, i, i_rnspacl)); + nsinfo[i].initnspacl = pg_strdup(PQgetvalue(res, i, i_initnspacl)); + nsinfo[i].initrnspacl = pg_strdup(PQgetvalue(res, i, i_initrnspacl)); + + /* Decide whether to dump this namespace */ + selectDumpableNamespace(&nsinfo[i], fout); + + /* + * Do not try to dump ACL if the ACL is empty or the default. + * + * This is useful because, for some schemas/objects, the only + * component we are going to try and dump is the ACL and if we can + * remove that then 'dump' goes to zero/false and we don't consider + * this object for dumping at all later on. + */ + if (PQgetisnull(res, i, i_nspacl) && PQgetisnull(res, i, i_rnspacl) && + PQgetisnull(res, i, i_initnspacl) && + PQgetisnull(res, i, i_initrnspacl)) + nsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + if (strlen(nsinfo[i].rolname) == 0) + pg_log_warning("owner of schema \"%s\" appears to be invalid", + nsinfo[i].dobj.name); + } + + PQclear(res); + destroyPQExpBuffer(query); + + *numNamespaces = ntups; + + return nsinfo; +} + +/* + * findNamespace: + * given a namespace OID, look up the info read by getNamespaces + */ +static NamespaceInfo * +findNamespace(Oid nsoid) +{ + NamespaceInfo *nsinfo; + + nsinfo = findNamespaceByOid(nsoid); + if (nsinfo == NULL) + fatal("schema with OID %u does not exist", nsoid); + return nsinfo; +} + +/* + * getExtensions: + * read all extensions in the system catalogs and return them in the + * ExtensionInfo* structure + * + * numExtensions is set to the number of extensions read in + */ +ExtensionInfo * +getExtensions(Archive *fout, int *numExtensions) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + ExtensionInfo *extinfo; + int i_tableoid; + int i_oid; + int i_extname; + int i_nspname; + int i_extrelocatable; + int i_extversion; + int i_extconfig; + int i_extcondition; + + /* + * Before 9.1, there are no extensions. + */ + if (fout->remoteVersion < 90100) + { + *numExtensions = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, " + "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition " + "FROM pg_extension x " + "JOIN pg_namespace n ON n.oid = x.extnamespace"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + extinfo = (ExtensionInfo *) pg_malloc(ntups * sizeof(ExtensionInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_extname = PQfnumber(res, "extname"); + i_nspname = PQfnumber(res, "nspname"); + i_extrelocatable = PQfnumber(res, "extrelocatable"); + i_extversion = PQfnumber(res, "extversion"); + i_extconfig = PQfnumber(res, "extconfig"); + i_extcondition = PQfnumber(res, "extcondition"); + + for (i = 0; i < ntups; i++) + { + extinfo[i].dobj.objType = DO_EXTENSION; + extinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&extinfo[i].dobj); + extinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_extname)); + extinfo[i].namespace = pg_strdup(PQgetvalue(res, i, i_nspname)); + extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't'; + extinfo[i].extversion = pg_strdup(PQgetvalue(res, i, i_extversion)); + extinfo[i].extconfig = pg_strdup(PQgetvalue(res, i, i_extconfig)); + extinfo[i].extcondition = pg_strdup(PQgetvalue(res, i, i_extcondition)); + + /* Decide whether we want to dump it */ + selectDumpableExtension(&(extinfo[i]), dopt); + } + + PQclear(res); + destroyPQExpBuffer(query); + + *numExtensions = ntups; + + return extinfo; +} + +/* + * getTypes: + * read all types in the system catalogs and return them in the + * TypeInfo* structure + * + * numTypes is set to the number of types read in + * + * NB: this must run after getFuncs() because we assume we can do + * findFuncByOid(). + */ +TypeInfo * +getTypes(Archive *fout, int *numTypes) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + TypeInfo *tyinfo; + ShellTypeInfo *stinfo; + int i_tableoid; + int i_oid; + int i_typname; + int i_typnamespace; + int i_typacl; + int i_rtypacl; + int i_inittypacl; + int i_initrtypacl; + int i_rolname; + int i_typelem; + int i_typrelid; + int i_typrelkind; + int i_typtype; + int i_typisdefined; + int i_isarray; + + /* + * we include even the built-in types because those may be used as array + * elements by user-defined types + * + * we filter out the built-in types when we dump out the types + * + * same approach for undefined (shell) types and array types + * + * Note: as of 8.3 we can reliably detect whether a type is an + * auto-generated array type by checking the element type's typarray. + * (Before that the test is capable of generating false positives.) We + * still check for name beginning with '_', though, so as to avoid the + * cost of the subselect probe for all standard types. This would have to + * be revisited if the backend ever allows renaming of array types. + */ + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "t.typacl", "t.typowner", "'T'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, "SELECT t.tableoid, t.oid, t.typname, " + "t.typnamespace, " + "%s AS typacl, " + "%s AS rtypacl, " + "%s AS inittypacl, " + "%s AS initrtypacl, " + "(%s t.typowner) AS rolname, " + "t.typelem, t.typrelid, " + "CASE WHEN t.typrelid = 0 THEN ' '::\"char\" " + "ELSE (SELECT relkind FROM pg_class WHERE oid = t.typrelid) END AS typrelkind, " + "t.typtype, t.typisdefined, " + "t.typname[0] = '_' AND t.typelem != 0 AND " + "(SELECT typarray FROM pg_type te WHERE oid = t.typelem) = t.oid AS isarray " + "FROM pg_type t " + "LEFT JOIN pg_init_privs pip ON " + "(t.oid = pip.objoid " + "AND pip.classoid = 'pg_type'::regclass " + "AND pip.objsubid = 0) ", + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + username_subquery); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else if (fout->remoteVersion >= 90200) + { + appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " + "typnamespace, typacl, NULL as rtypacl, " + "NULL AS inittypacl, NULL AS initrtypacl, " + "(%s typowner) AS rolname, " + "typelem, typrelid, " + "CASE WHEN typrelid = 0 THEN ' '::\"char\" " + "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AND " + "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray " + "FROM pg_type", + username_subquery); + } + else if (fout->remoteVersion >= 80300) + { + appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " + "typnamespace, NULL AS typacl, NULL as rtypacl, " + "NULL AS inittypacl, NULL AS initrtypacl, " + "(%s typowner) AS rolname, " + "typelem, typrelid, " + "CASE WHEN typrelid = 0 THEN ' '::\"char\" " + "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AND " + "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray " + "FROM pg_type", + username_subquery); + } + else + { + appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " + "typnamespace, NULL AS typacl, NULL as rtypacl, " + "NULL AS inittypacl, NULL AS initrtypacl, " + "(%s typowner) AS rolname, " + "typelem, typrelid, " + "CASE WHEN typrelid = 0 THEN ' '::\"char\" " + "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AS isarray " + "FROM pg_type", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + tyinfo = (TypeInfo *) pg_malloc(ntups * sizeof(TypeInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_typname = PQfnumber(res, "typname"); + i_typnamespace = PQfnumber(res, "typnamespace"); + i_typacl = PQfnumber(res, "typacl"); + i_rtypacl = PQfnumber(res, "rtypacl"); + i_inittypacl = PQfnumber(res, "inittypacl"); + i_initrtypacl = PQfnumber(res, "initrtypacl"); + i_rolname = PQfnumber(res, "rolname"); + i_typelem = PQfnumber(res, "typelem"); + i_typrelid = PQfnumber(res, "typrelid"); + i_typrelkind = PQfnumber(res, "typrelkind"); + i_typtype = PQfnumber(res, "typtype"); + i_typisdefined = PQfnumber(res, "typisdefined"); + i_isarray = PQfnumber(res, "isarray"); + + for (i = 0; i < ntups; i++) + { + tyinfo[i].dobj.objType = DO_TYPE; + tyinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&tyinfo[i].dobj); + tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname)); + tyinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_typnamespace))); + tyinfo[i].ftypname = NULL; /* may get filled later */ + tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl)); + tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl)); + tyinfo[i].inittypacl = pg_strdup(PQgetvalue(res, i, i_inittypacl)); + tyinfo[i].initrtypacl = pg_strdup(PQgetvalue(res, i, i_initrtypacl)); + tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem)); + tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid)); + tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind); + tyinfo[i].typtype = *PQgetvalue(res, i, i_typtype); + tyinfo[i].shellType = NULL; + + if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0) + tyinfo[i].isDefined = true; + else + tyinfo[i].isDefined = false; + + if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0) + tyinfo[i].isArray = true; + else + tyinfo[i].isArray = false; + + if (tyinfo[i].typtype == 'm') + tyinfo[i].isMultirange = true; + else + tyinfo[i].isMultirange = false; + + /* Decide whether we want to dump it */ + selectDumpableType(&tyinfo[i], fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_typacl) && PQgetisnull(res, i, i_rtypacl) && + PQgetisnull(res, i, i_inittypacl) && + PQgetisnull(res, i, i_initrtypacl)) + tyinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + /* + * If it's a domain, fetch info about its constraints, if any + */ + tyinfo[i].nDomChecks = 0; + tyinfo[i].domChecks = NULL; + if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) && + tyinfo[i].typtype == TYPTYPE_DOMAIN) + getDomainConstraints(fout, &(tyinfo[i])); + + /* + * If it's a base type, make a DumpableObject representing a shell + * definition of the type. We will need to dump that ahead of the I/O + * functions for the type. Similarly, range types need a shell + * definition in case they have a canonicalize function. + * + * Note: the shell type doesn't have a catId. You might think it + * should copy the base type's catId, but then it might capture the + * pg_depend entries for the type, which we don't want. + */ + if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) && + (tyinfo[i].typtype == TYPTYPE_BASE || + tyinfo[i].typtype == TYPTYPE_RANGE)) + { + stinfo = (ShellTypeInfo *) pg_malloc(sizeof(ShellTypeInfo)); + stinfo->dobj.objType = DO_SHELL_TYPE; + stinfo->dobj.catId = nilCatalogId; + AssignDumpId(&stinfo->dobj); + stinfo->dobj.name = pg_strdup(tyinfo[i].dobj.name); + stinfo->dobj.namespace = tyinfo[i].dobj.namespace; + stinfo->baseType = &(tyinfo[i]); + tyinfo[i].shellType = stinfo; + + /* + * Initially mark the shell type as not to be dumped. We'll only + * dump it if the I/O or canonicalize functions need to be dumped; + * this is taken care of while sorting dependencies. + */ + stinfo->dobj.dump = DUMP_COMPONENT_NONE; + } + + if (strlen(tyinfo[i].rolname) == 0) + pg_log_warning("owner of data type \"%s\" appears to be invalid", + tyinfo[i].dobj.name); + } + + *numTypes = ntups; + + PQclear(res); + + destroyPQExpBuffer(query); + + return tyinfo; +} + +/* + * getOperators: + * read all operators in the system catalogs and return them in the + * OprInfo* structure + * + * numOprs is set to the number of operators read in + */ +OprInfo * +getOperators(Archive *fout, int *numOprs) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + OprInfo *oprinfo; + int i_tableoid; + int i_oid; + int i_oprname; + int i_oprnamespace; + int i_rolname; + int i_oprkind; + int i_oprcode; + + /* + * find all operators, including builtin operators; we filter out + * system-defined operators at dump-out time. + */ + + appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, " + "oprnamespace, " + "(%s oprowner) AS rolname, " + "oprkind, " + "oprcode::oid AS oprcode " + "FROM pg_operator", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numOprs = ntups; + + oprinfo = (OprInfo *) pg_malloc(ntups * sizeof(OprInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_oprname = PQfnumber(res, "oprname"); + i_oprnamespace = PQfnumber(res, "oprnamespace"); + i_rolname = PQfnumber(res, "rolname"); + i_oprkind = PQfnumber(res, "oprkind"); + i_oprcode = PQfnumber(res, "oprcode"); + + for (i = 0; i < ntups; i++) + { + oprinfo[i].dobj.objType = DO_OPERATOR; + oprinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&oprinfo[i].dobj); + oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname)); + oprinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace))); + oprinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + oprinfo[i].oprkind = (PQgetvalue(res, i, i_oprkind))[0]; + oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(oprinfo[i].dobj), fout); + + /* Operators do not currently have ACLs. */ + oprinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + if (strlen(oprinfo[i].rolname) == 0) + pg_log_warning("owner of operator \"%s\" appears to be invalid", + oprinfo[i].dobj.name); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return oprinfo; +} + +/* + * getCollations: + * read all collations in the system catalogs and return them in the + * CollInfo* structure + * + * numCollations is set to the number of collations read in + */ +CollInfo * +getCollations(Archive *fout, int *numCollations) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + CollInfo *collinfo; + int i_tableoid; + int i_oid; + int i_collname; + int i_collnamespace; + int i_rolname; + + /* Collations didn't exist pre-9.1 */ + if (fout->remoteVersion < 90100) + { + *numCollations = 0; + return NULL; + } + + query = createPQExpBuffer(); + + /* + * find all collations, including builtin collations; we filter out + * system-defined collations at dump-out time. + */ + + appendPQExpBuffer(query, "SELECT tableoid, oid, collname, " + "collnamespace, " + "(%s collowner) AS rolname " + "FROM pg_collation", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numCollations = ntups; + + collinfo = (CollInfo *) pg_malloc(ntups * sizeof(CollInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_collname = PQfnumber(res, "collname"); + i_collnamespace = PQfnumber(res, "collnamespace"); + i_rolname = PQfnumber(res, "rolname"); + + for (i = 0; i < ntups; i++) + { + collinfo[i].dobj.objType = DO_COLLATION; + collinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&collinfo[i].dobj); + collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname)); + collinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_collnamespace))); + collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(collinfo[i].dobj), fout); + + /* Collations do not currently have ACLs. */ + collinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return collinfo; +} + +/* + * getConversions: + * read all conversions in the system catalogs and return them in the + * ConvInfo* structure + * + * numConversions is set to the number of conversions read in + */ +ConvInfo * +getConversions(Archive *fout, int *numConversions) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + ConvInfo *convinfo; + int i_tableoid; + int i_oid; + int i_conname; + int i_connamespace; + int i_rolname; + + query = createPQExpBuffer(); + + /* + * find all conversions, including builtin conversions; we filter out + * system-defined conversions at dump-out time. + */ + + appendPQExpBuffer(query, "SELECT tableoid, oid, conname, " + "connamespace, " + "(%s conowner) AS rolname " + "FROM pg_conversion", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numConversions = ntups; + + convinfo = (ConvInfo *) pg_malloc(ntups * sizeof(ConvInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_conname = PQfnumber(res, "conname"); + i_connamespace = PQfnumber(res, "connamespace"); + i_rolname = PQfnumber(res, "rolname"); + + for (i = 0; i < ntups; i++) + { + convinfo[i].dobj.objType = DO_CONVERSION; + convinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&convinfo[i].dobj); + convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname)); + convinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_connamespace))); + convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(convinfo[i].dobj), fout); + + /* Conversions do not currently have ACLs. */ + convinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return convinfo; +} + +/* + * getAccessMethods: + * read all user-defined access methods in the system catalogs and return + * them in the AccessMethodInfo* structure + * + * numAccessMethods is set to the number of access methods read in + */ +AccessMethodInfo * +getAccessMethods(Archive *fout, int *numAccessMethods) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + AccessMethodInfo *aminfo; + int i_tableoid; + int i_oid; + int i_amname; + int i_amhandler; + int i_amtype; + + /* Before 9.6, there are no user-defined access methods */ + if (fout->remoteVersion < 90600) + { + *numAccessMethods = 0; + return NULL; + } + + query = createPQExpBuffer(); + + /* Select all access methods from pg_am table */ + appendPQExpBufferStr(query, "SELECT tableoid, oid, amname, amtype, " + "amhandler::pg_catalog.regproc AS amhandler " + "FROM pg_am"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numAccessMethods = ntups; + + aminfo = (AccessMethodInfo *) pg_malloc(ntups * sizeof(AccessMethodInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_amname = PQfnumber(res, "amname"); + i_amhandler = PQfnumber(res, "amhandler"); + i_amtype = PQfnumber(res, "amtype"); + + for (i = 0; i < ntups; i++) + { + aminfo[i].dobj.objType = DO_ACCESS_METHOD; + aminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + aminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&aminfo[i].dobj); + aminfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_amname)); + aminfo[i].dobj.namespace = NULL; + aminfo[i].amhandler = pg_strdup(PQgetvalue(res, i, i_amhandler)); + aminfo[i].amtype = *(PQgetvalue(res, i, i_amtype)); + + /* Decide whether we want to dump it */ + selectDumpableAccessMethod(&(aminfo[i]), fout); + + /* Access methods do not currently have ACLs. */ + aminfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return aminfo; +} + + +/* + * getOpclasses: + * read all opclasses in the system catalogs and return them in the + * OpclassInfo* structure + * + * numOpclasses is set to the number of opclasses read in + */ +OpclassInfo * +getOpclasses(Archive *fout, int *numOpclasses) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + OpclassInfo *opcinfo; + int i_tableoid; + int i_oid; + int i_opcname; + int i_opcnamespace; + int i_rolname; + + /* + * find all opclasses, including builtin opclasses; we filter out + * system-defined opclasses at dump-out time. + */ + + appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, " + "opcnamespace, " + "(%s opcowner) AS rolname " + "FROM pg_opclass", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numOpclasses = ntups; + + opcinfo = (OpclassInfo *) pg_malloc(ntups * sizeof(OpclassInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_opcname = PQfnumber(res, "opcname"); + i_opcnamespace = PQfnumber(res, "opcnamespace"); + i_rolname = PQfnumber(res, "rolname"); + + for (i = 0; i < ntups; i++) + { + opcinfo[i].dobj.objType = DO_OPCLASS; + opcinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&opcinfo[i].dobj); + opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname)); + opcinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace))); + opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(opcinfo[i].dobj), fout); + + /* Op Classes do not currently have ACLs. */ + opcinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + if (strlen(opcinfo[i].rolname) == 0) + pg_log_warning("owner of operator class \"%s\" appears to be invalid", + opcinfo[i].dobj.name); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return opcinfo; +} + +/* + * getOpfamilies: + * read all opfamilies in the system catalogs and return them in the + * OpfamilyInfo* structure + * + * numOpfamilies is set to the number of opfamilies read in + */ +OpfamilyInfo * +getOpfamilies(Archive *fout, int *numOpfamilies) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + OpfamilyInfo *opfinfo; + int i_tableoid; + int i_oid; + int i_opfname; + int i_opfnamespace; + int i_rolname; + + /* Before 8.3, there is no separate concept of opfamilies */ + if (fout->remoteVersion < 80300) + { + *numOpfamilies = 0; + return NULL; + } + + query = createPQExpBuffer(); + + /* + * find all opfamilies, including builtin opfamilies; we filter out + * system-defined opfamilies at dump-out time. + */ + + appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, " + "opfnamespace, " + "(%s opfowner) AS rolname " + "FROM pg_opfamily", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numOpfamilies = ntups; + + opfinfo = (OpfamilyInfo *) pg_malloc(ntups * sizeof(OpfamilyInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_opfname = PQfnumber(res, "opfname"); + i_opfnamespace = PQfnumber(res, "opfnamespace"); + i_rolname = PQfnumber(res, "rolname"); + + for (i = 0; i < ntups; i++) + { + opfinfo[i].dobj.objType = DO_OPFAMILY; + opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&opfinfo[i].dobj); + opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname)); + opfinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace))); + opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(opfinfo[i].dobj), fout); + + /* Extensions do not currently have ACLs. */ + opfinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + if (strlen(opfinfo[i].rolname) == 0) + pg_log_warning("owner of operator family \"%s\" appears to be invalid", + opfinfo[i].dobj.name); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return opfinfo; +} + +/* + * getAggregates: + * read all the user-defined aggregates in the system catalogs and + * return them in the AggInfo* structure + * + * numAggs is set to the number of aggregates read in + */ +AggInfo * +getAggregates(Archive *fout, int *numAggs) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + AggInfo *agginfo; + int i_tableoid; + int i_oid; + int i_aggname; + int i_aggnamespace; + int i_pronargs; + int i_proargtypes; + int i_rolname; + int i_aggacl; + int i_raggacl; + int i_initaggacl; + int i_initraggacl; + + /* + * Find all interesting aggregates. See comment in getFuncs() for the + * rationale behind the filtering logic. + */ + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + const char *agg_check; + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "p.proacl", "p.proowner", "'f'", + dopt->binary_upgrade); + + agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'" + : "p.proisagg"); + + appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, " + "p.proname AS aggname, " + "p.pronamespace AS aggnamespace, " + "p.pronargs, p.proargtypes, " + "(%s p.proowner) AS rolname, " + "%s AS aggacl, " + "%s AS raggacl, " + "%s AS initaggacl, " + "%s AS initraggacl " + "FROM pg_proc p " + "LEFT JOIN pg_init_privs pip ON " + "(p.oid = pip.objoid " + "AND pip.classoid = 'pg_proc'::regclass " + "AND pip.objsubid = 0) " + "WHERE %s AND (" + "p.pronamespace != " + "(SELECT oid FROM pg_namespace " + "WHERE nspname = 'pg_catalog') OR " + "p.proacl IS DISTINCT FROM pip.initprivs", + username_subquery, + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + agg_check); + if (dopt->binary_upgrade) + appendPQExpBufferStr(query, + " OR EXISTS(SELECT 1 FROM pg_depend WHERE " + "classid = 'pg_proc'::regclass AND " + "objid = p.oid AND " + "refclassid = 'pg_extension'::regclass AND " + "deptype = 'e')"); + appendPQExpBufferChar(query, ')'); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else if (fout->remoteVersion >= 80200) + { + appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, " + "pronamespace AS aggnamespace, " + "pronargs, proargtypes, " + "(%s proowner) AS rolname, " + "proacl AS aggacl, " + "NULL AS raggacl, " + "NULL AS initaggacl, NULL AS initraggacl " + "FROM pg_proc p " + "WHERE proisagg AND (" + "pronamespace != " + "(SELECT oid FROM pg_namespace " + "WHERE nspname = 'pg_catalog')", + username_subquery); + if (dopt->binary_upgrade && fout->remoteVersion >= 90100) + appendPQExpBufferStr(query, + " OR EXISTS(SELECT 1 FROM pg_depend WHERE " + "classid = 'pg_proc'::regclass AND " + "objid = p.oid AND " + "refclassid = 'pg_extension'::regclass AND " + "deptype = 'e')"); + appendPQExpBufferChar(query, ')'); + } + else + { + appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, " + "pronamespace AS aggnamespace, " + "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, " + "proargtypes, " + "(%s proowner) AS rolname, " + "proacl AS aggacl, " + "NULL AS raggacl, " + "NULL AS initaggacl, NULL AS initraggacl " + "FROM pg_proc " + "WHERE proisagg " + "AND pronamespace != " + "(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numAggs = ntups; + + agginfo = (AggInfo *) pg_malloc(ntups * sizeof(AggInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_aggname = PQfnumber(res, "aggname"); + i_aggnamespace = PQfnumber(res, "aggnamespace"); + i_pronargs = PQfnumber(res, "pronargs"); + i_proargtypes = PQfnumber(res, "proargtypes"); + i_rolname = PQfnumber(res, "rolname"); + i_aggacl = PQfnumber(res, "aggacl"); + i_raggacl = PQfnumber(res, "raggacl"); + i_initaggacl = PQfnumber(res, "initaggacl"); + i_initraggacl = PQfnumber(res, "initraggacl"); + + for (i = 0; i < ntups; i++) + { + agginfo[i].aggfn.dobj.objType = DO_AGG; + agginfo[i].aggfn.dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&agginfo[i].aggfn.dobj); + agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname)); + agginfo[i].aggfn.dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace))); + agginfo[i].aggfn.rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + if (strlen(agginfo[i].aggfn.rolname) == 0) + pg_log_warning("owner of aggregate function \"%s\" appears to be invalid", + agginfo[i].aggfn.dobj.name); + agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */ + agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */ + agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl)); + agginfo[i].aggfn.rproacl = pg_strdup(PQgetvalue(res, i, i_raggacl)); + agginfo[i].aggfn.initproacl = pg_strdup(PQgetvalue(res, i, i_initaggacl)); + agginfo[i].aggfn.initrproacl = pg_strdup(PQgetvalue(res, i, i_initraggacl)); + agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs)); + if (agginfo[i].aggfn.nargs == 0) + agginfo[i].aggfn.argtypes = NULL; + else + { + agginfo[i].aggfn.argtypes = (Oid *) pg_malloc(agginfo[i].aggfn.nargs * sizeof(Oid)); + parseOidArray(PQgetvalue(res, i, i_proargtypes), + agginfo[i].aggfn.argtypes, + agginfo[i].aggfn.nargs); + } + + /* Decide whether we want to dump it */ + selectDumpableObject(&(agginfo[i].aggfn.dobj), fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_aggacl) && PQgetisnull(res, i, i_raggacl) && + PQgetisnull(res, i, i_initaggacl) && + PQgetisnull(res, i, i_initraggacl)) + agginfo[i].aggfn.dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return agginfo; +} + +/* + * getFuncs: + * read all the user-defined functions in the system catalogs and + * return them in the FuncInfo* structure + * + * numFuncs is set to the number of functions read in + */ +FuncInfo * +getFuncs(Archive *fout, int *numFuncs) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + FuncInfo *finfo; + int i_tableoid; + int i_oid; + int i_proname; + int i_pronamespace; + int i_rolname; + int i_prolang; + int i_pronargs; + int i_proargtypes; + int i_prorettype; + int i_proacl; + int i_rproacl; + int i_initproacl; + int i_initrproacl; + + /* + * Find all interesting functions. This is a bit complicated: + * + * 1. Always exclude aggregates; those are handled elsewhere. + * + * 2. Always exclude functions that are internally dependent on something + * else, since presumably those will be created as a result of creating + * the something else. This currently acts only to suppress constructor + * functions for range types (so we only need it in 9.2 and up). Note + * this is OK only because the constructors don't have any dependencies + * the range type doesn't have; otherwise we might not get creation + * ordering correct. + * + * 3. Otherwise, we normally exclude functions in pg_catalog. However, if + * they're members of extensions and we are in binary-upgrade mode then + * include them, since we want to dump extension members individually in + * that mode. Also, if they are used by casts or transforms then we need + * to gather the information about them, though they won't be dumped if + * they are built-in. Also, in 9.6 and up, include functions in + * pg_catalog if they have an ACL different from what's shown in + * pg_init_privs. + */ + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + const char *not_agg_check; + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "p.proacl", "p.proowner", "'f'", + dopt->binary_upgrade); + + not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'" + : "NOT p.proisagg"); + + appendPQExpBuffer(query, + "SELECT p.tableoid, p.oid, p.proname, p.prolang, " + "p.pronargs, p.proargtypes, p.prorettype, " + "%s AS proacl, " + "%s AS rproacl, " + "%s AS initproacl, " + "%s AS initrproacl, " + "p.pronamespace, " + "(%s p.proowner) AS rolname " + "FROM pg_proc p " + "LEFT JOIN pg_init_privs pip ON " + "(p.oid = pip.objoid " + "AND pip.classoid = 'pg_proc'::regclass " + "AND pip.objsubid = 0) " + "WHERE %s" + "\n AND NOT EXISTS (SELECT 1 FROM pg_depend " + "WHERE classid = 'pg_proc'::regclass AND " + "objid = p.oid AND deptype = 'i')" + "\n AND (" + "\n pronamespace != " + "(SELECT oid FROM pg_namespace " + "WHERE nspname = 'pg_catalog')" + "\n OR EXISTS (SELECT 1 FROM pg_cast" + "\n WHERE pg_cast.oid > %u " + "\n AND p.oid = pg_cast.castfunc)" + "\n OR EXISTS (SELECT 1 FROM pg_transform" + "\n WHERE pg_transform.oid > %u AND " + "\n (p.oid = pg_transform.trffromsql" + "\n OR p.oid = pg_transform.trftosql))", + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + username_subquery, + not_agg_check, + g_last_builtin_oid, + g_last_builtin_oid); + if (dopt->binary_upgrade) + appendPQExpBufferStr(query, + "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE " + "classid = 'pg_proc'::regclass AND " + "objid = p.oid AND " + "refclassid = 'pg_extension'::regclass AND " + "deptype = 'e')"); + appendPQExpBufferStr(query, + "\n OR p.proacl IS DISTINCT FROM pip.initprivs"); + appendPQExpBufferChar(query, ')'); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else + { + appendPQExpBuffer(query, + "SELECT tableoid, oid, proname, prolang, " + "pronargs, proargtypes, prorettype, proacl, " + "NULL as rproacl, " + "NULL as initproacl, NULL AS initrproacl, " + "pronamespace, " + "(%s proowner) AS rolname " + "FROM pg_proc p " + "WHERE NOT proisagg", + username_subquery); + if (fout->remoteVersion >= 90200) + appendPQExpBufferStr(query, + "\n AND NOT EXISTS (SELECT 1 FROM pg_depend " + "WHERE classid = 'pg_proc'::regclass AND " + "objid = p.oid AND deptype = 'i')"); + appendPQExpBuffer(query, + "\n AND (" + "\n pronamespace != " + "(SELECT oid FROM pg_namespace " + "WHERE nspname = 'pg_catalog')" + "\n OR EXISTS (SELECT 1 FROM pg_cast" + "\n WHERE pg_cast.oid > '%u'::oid" + "\n AND p.oid = pg_cast.castfunc)", + g_last_builtin_oid); + + if (fout->remoteVersion >= 90500) + appendPQExpBuffer(query, + "\n OR EXISTS (SELECT 1 FROM pg_transform" + "\n WHERE pg_transform.oid > '%u'::oid" + "\n AND (p.oid = pg_transform.trffromsql" + "\n OR p.oid = pg_transform.trftosql))", + g_last_builtin_oid); + + if (dopt->binary_upgrade && fout->remoteVersion >= 90100) + appendPQExpBufferStr(query, + "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE " + "classid = 'pg_proc'::regclass AND " + "objid = p.oid AND " + "refclassid = 'pg_extension'::regclass AND " + "deptype = 'e')"); + appendPQExpBufferChar(query, ')'); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numFuncs = ntups; + + finfo = (FuncInfo *) pg_malloc0(ntups * sizeof(FuncInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_proname = PQfnumber(res, "proname"); + i_pronamespace = PQfnumber(res, "pronamespace"); + i_rolname = PQfnumber(res, "rolname"); + i_prolang = PQfnumber(res, "prolang"); + i_pronargs = PQfnumber(res, "pronargs"); + i_proargtypes = PQfnumber(res, "proargtypes"); + i_prorettype = PQfnumber(res, "prorettype"); + i_proacl = PQfnumber(res, "proacl"); + i_rproacl = PQfnumber(res, "rproacl"); + i_initproacl = PQfnumber(res, "initproacl"); + i_initrproacl = PQfnumber(res, "initrproacl"); + + for (i = 0; i < ntups; i++) + { + finfo[i].dobj.objType = DO_FUNC; + finfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&finfo[i].dobj); + finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname)); + finfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_pronamespace))); + finfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang)); + finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype)); + finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl)); + finfo[i].rproacl = pg_strdup(PQgetvalue(res, i, i_rproacl)); + finfo[i].initproacl = pg_strdup(PQgetvalue(res, i, i_initproacl)); + finfo[i].initrproacl = pg_strdup(PQgetvalue(res, i, i_initrproacl)); + finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); + if (finfo[i].nargs == 0) + finfo[i].argtypes = NULL; + else + { + finfo[i].argtypes = (Oid *) pg_malloc(finfo[i].nargs * sizeof(Oid)); + parseOidArray(PQgetvalue(res, i, i_proargtypes), + finfo[i].argtypes, finfo[i].nargs); + } + + /* Decide whether we want to dump it */ + selectDumpableObject(&(finfo[i].dobj), fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_proacl) && PQgetisnull(res, i, i_rproacl) && + PQgetisnull(res, i, i_initproacl) && + PQgetisnull(res, i, i_initrproacl)) + finfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + if (strlen(finfo[i].rolname) == 0) + pg_log_warning("owner of function \"%s\" appears to be invalid", + finfo[i].dobj.name); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return finfo; +} + +/* + * getTables + * read all the tables (no indexes) + * in the system catalogs return them in the TableInfo* structure + * + * numTables is set to the number of tables read in + */ +TableInfo * +getTables(Archive *fout, int *numTables) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + TableInfo *tblinfo; + int i_reltableoid; + int i_reloid; + int i_relname; + int i_relnamespace; + int i_relkind; + int i_relacl; + int i_rrelacl; + int i_initrelacl; + int i_initrrelacl; + int i_rolname; + int i_relchecks; + int i_relhastriggers; + int i_relhasindex; + int i_relhasrules; + int i_relrowsec; + int i_relforcerowsec; + int i_relhasoids; + int i_relfrozenxid; + int i_relminmxid; + int i_toastoid; + int i_toastfrozenxid; + int i_toastminmxid; + int i_relpersistence; + int i_relispopulated; + int i_relreplident; + int i_owning_tab; + int i_owning_col; + int i_reltablespace; + int i_reloptions; + int i_checkoption; + int i_toastreloptions; + int i_reloftype; + int i_relpages; + int i_foreignserver; + int i_is_identity_sequence; + int i_changed_acl; + int i_partkeydef; + int i_ispartition; + int i_partbound; + int i_amname; + + /* + * Find all the tables and table-like objects. + * + * We include system catalogs, so that we can work if a user table is + * defined to inherit from a system catalog (pretty weird, but...) + * + * We ignore relations that are not ordinary tables, sequences, views, + * materialized views, composite types, or foreign tables. + * + * Composite-type table entries won't be dumped as such, but we have to + * make a DumpableObject for them so that we can track dependencies of the + * composite type (pg_depend entries for columns of the composite type + * link to the pg_class entry not the pg_type entry). + * + * Note: in this phase we should collect only a minimal amount of + * information about each table, basically just enough to decide if it is + * interesting. We must fetch all tables in this phase because otherwise + * we cannot correctly identify inherited columns, owned sequences, etc. + * + * We purposefully ignore toast OIDs for partitioned tables; the reason is + * that versions 10 and 11 have them, but 12 does not, so emitting them + * causes the upgrade to fail. + */ + + if (fout->remoteVersion >= 90600) + { + char *partkeydef = "NULL"; + char *ispartition = "false"; + char *partbound = "NULL"; + char *relhasoids = "c.relhasoids"; + + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + PQExpBuffer attacl_subquery = createPQExpBuffer(); + PQExpBuffer attracl_subquery = createPQExpBuffer(); + PQExpBuffer attinitacl_subquery = createPQExpBuffer(); + PQExpBuffer attinitracl_subquery = createPQExpBuffer(); + + /* + * Collect the information about any partitioned tables, which were + * added in PG10. + */ + + if (fout->remoteVersion >= 100000) + { + partkeydef = "pg_get_partkeydef(c.oid)"; + ispartition = "c.relispartition"; + partbound = "pg_get_expr(c.relpartbound, c.oid)"; + } + + /* In PG12 upwards WITH OIDS does not exist anymore. */ + if (fout->remoteVersion >= 120000) + relhasoids = "'f'::bool"; + + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + * + * Left join to detect if any privileges are still as-set-at-init, in + * which case we won't dump out ACL commands for those. + */ + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "c.relacl", "c.relowner", + "CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE) + " THEN 's' ELSE 'r' END::\"char\"", + dopt->binary_upgrade); + + buildACLQueries(attacl_subquery, attracl_subquery, attinitacl_subquery, + attinitracl_subquery, "at.attacl", "c.relowner", "'c'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "%s AS relacl, %s as rrelacl, " + "%s AS initrelacl, %s as initrrelacl, " + "c.relkind, c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, %s AS relhasoids, " + "c.relrowsecurity, c.relforcerowsecurity, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " + "c.relpersistence, c.relispopulated, " + "c.relreplident, c.relpages, am.amname, " + "CASE WHEN c.relkind = 'f' THEN " + "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) " + "ELSE 0 END AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " + "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " + "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " + "tc.reloptions AS toast_reloptions, " + "c.relkind = '%c' AND EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_class'::regclass AND objid = c.oid AND objsubid = 0 AND refclassid = 'pg_class'::regclass AND deptype = 'i') AS is_identity_sequence, " + "EXISTS (SELECT 1 FROM pg_attribute at LEFT JOIN pg_init_privs pip ON " + "(c.oid = pip.objoid " + "AND pip.classoid = 'pg_class'::regclass " + "AND pip.objsubid = at.attnum)" + "WHERE at.attrelid = c.oid AND (" + "%s IS NOT NULL " + "OR %s IS NOT NULL " + "OR %s IS NOT NULL " + "OR %s IS NOT NULL" + "))" + "AS changed_acl, " + "%s AS partkeydef, " + "%s AS ispartition, " + "%s AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype IN ('a', 'i')) " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid AND c.relkind <> '%c') " + "LEFT JOIN pg_am am ON (c.relam = am.oid) " + "LEFT JOIN pg_init_privs pip ON " + "(c.oid = pip.objoid " + "AND pip.classoid = 'pg_class'::regclass " + "AND pip.objsubid = 0) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + username_subquery, + relhasoids, + RELKIND_SEQUENCE, + attacl_subquery->data, + attracl_subquery->data, + attinitacl_subquery->data, + attinitracl_subquery->data, + partkeydef, + ispartition, + partbound, + RELKIND_SEQUENCE, + RELKIND_PARTITIONED_TABLE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE, + RELKIND_PARTITIONED_TABLE); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + + destroyPQExpBuffer(attacl_subquery); + destroyPQExpBuffer(attracl_subquery); + destroyPQExpBuffer(attinitacl_subquery); + destroyPQExpBuffer(attinitracl_subquery); + } + else if (fout->remoteVersion >= 90500) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "c.relrowsecurity, c.relforcerowsecurity, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " + "c.relpersistence, c.relispopulated, " + "c.relreplident, c.relpages, " + "NULL AS amname, " + "CASE WHEN c.relkind = 'f' THEN " + "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) " + "ELSE 0 END AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " + "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " + "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE); + } + else if (fout->remoteVersion >= 90400) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " + "c.relpersistence, c.relispopulated, " + "c.relreplident, c.relpages, " + "NULL AS amname, " + "CASE WHEN c.relkind = 'f' THEN " + "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) " + "ELSE 0 END AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " + "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " + "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE); + } + else if (fout->remoteVersion >= 90300) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " + "c.relpersistence, c.relispopulated, " + "'d' AS relreplident, c.relpages, " + "NULL AS amname, " + "CASE WHEN c.relkind = 'f' THEN " + "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) " + "ELSE 0 END AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " + "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " + "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE); + } + else if (fout->remoteVersion >= 90100) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " + "c.relpersistence, 't' as relispopulated, " + "'d' AS relreplident, c.relpages, " + "NULL AS amname, " + "CASE WHEN c.relkind = 'f' THEN " + "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) " + "ELSE 0 END AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "c.reloptions AS reloptions, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE); + } + else if (fout->remoteVersion >= 90000) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " + "'p' AS relpersistence, 't' as relispopulated, " + "'d' AS relreplident, c.relpages, " + "NULL AS amname, " + "NULL AS foreignserver, " + "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "c.reloptions AS reloptions, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); + } + else if (fout->remoteVersion >= 80400) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, c.relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " + "'p' AS relpersistence, 't' as relispopulated, " + "'d' AS relreplident, c.relpages, " + "NULL AS amname, " + "NULL AS foreignserver, " + "NULL AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "c.reloptions AS reloptions, " + "tc.reloptions AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); + } + else if (fout->remoteVersion >= 80200) + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any (note this dependency is AUTO as of 8.2) + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, c.relname, " + "c.relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "c.relkind, " + "c.relnamespace, " + "(%s c.relowner) AS rolname, " + "c.relchecks, (c.reltriggers <> 0) AS relhastriggers, " + "c.relhasindex, c.relhasrules, c.relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " + "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " + "'p' AS relpersistence, 't' as relispopulated, " + "'d' AS relreplident, c.relpages, " + "NULL AS amname, " + "NULL AS foreignserver, " + "NULL AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "c.reloptions AS reloptions, " + "NULL AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'a') " + "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) " + "WHERE c.relkind in ('%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); + } + else + { + /* + * Left join to pick up dependency info linking sequences to their + * owning column, if any + */ + appendPQExpBuffer(query, + "SELECT c.tableoid, c.oid, relname, " + "relacl, NULL as rrelacl, " + "NULL AS initrelacl, NULL AS initrrelacl, " + "relkind, relnamespace, " + "(%s relowner) AS rolname, " + "relchecks, (reltriggers <> 0) AS relhastriggers, " + "relhasindex, relhasrules, relhasoids, " + "'f'::bool AS relrowsecurity, " + "'f'::bool AS relforcerowsecurity, " + "0 AS relfrozenxid, 0 AS relminmxid," + "0 AS toid, " + "0 AS tfrozenxid, 0 AS tminmxid," + "'p' AS relpersistence, 't' as relispopulated, " + "'d' AS relreplident, relpages, " + "NULL AS amname, " + "NULL AS foreignserver, " + "NULL AS reloftype, " + "d.refobjid AS owning_tab, " + "d.refobjsubid AS owning_col, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " + "NULL AS reloptions, " + "NULL AS toast_reloptions, " + "NULL AS changed_acl, " + "NULL AS partkeydef, " + "false AS ispartition, " + "NULL AS partbound " + "FROM pg_class c " + "LEFT JOIN pg_depend d ON " + "(c.relkind = '%c' AND " + "d.classid = c.tableoid AND d.objid = c.oid AND " + "d.objsubid = 0 AND " + "d.refclassid = c.tableoid AND d.deptype = 'i') " + "WHERE relkind in ('%c', '%c', '%c', '%c') " + "ORDER BY c.oid", + username_subquery, + RELKIND_SEQUENCE, + RELKIND_RELATION, RELKIND_SEQUENCE, + RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numTables = ntups; + + /* + * Extract data from result and lock dumpable tables. We do the locking + * before anything else, to minimize the window wherein a table could + * disappear under us. + * + * Note that we have to save info about all tables here, even when dumping + * only one, because we don't yet know which tables might be inheritance + * ancestors of the target table. + */ + tblinfo = (TableInfo *) pg_malloc0(ntups * sizeof(TableInfo)); + + i_reltableoid = PQfnumber(res, "tableoid"); + i_reloid = PQfnumber(res, "oid"); + i_relname = PQfnumber(res, "relname"); + i_relnamespace = PQfnumber(res, "relnamespace"); + i_relacl = PQfnumber(res, "relacl"); + i_rrelacl = PQfnumber(res, "rrelacl"); + i_initrelacl = PQfnumber(res, "initrelacl"); + i_initrrelacl = PQfnumber(res, "initrrelacl"); + i_relkind = PQfnumber(res, "relkind"); + i_rolname = PQfnumber(res, "rolname"); + i_relchecks = PQfnumber(res, "relchecks"); + i_relhastriggers = PQfnumber(res, "relhastriggers"); + i_relhasindex = PQfnumber(res, "relhasindex"); + i_relhasrules = PQfnumber(res, "relhasrules"); + i_relrowsec = PQfnumber(res, "relrowsecurity"); + i_relforcerowsec = PQfnumber(res, "relforcerowsecurity"); + i_relhasoids = PQfnumber(res, "relhasoids"); + i_relfrozenxid = PQfnumber(res, "relfrozenxid"); + i_relminmxid = PQfnumber(res, "relminmxid"); + i_toastoid = PQfnumber(res, "toid"); + i_toastfrozenxid = PQfnumber(res, "tfrozenxid"); + i_toastminmxid = PQfnumber(res, "tminmxid"); + i_relpersistence = PQfnumber(res, "relpersistence"); + i_relispopulated = PQfnumber(res, "relispopulated"); + i_relreplident = PQfnumber(res, "relreplident"); + i_relpages = PQfnumber(res, "relpages"); + i_foreignserver = PQfnumber(res, "foreignserver"); + i_owning_tab = PQfnumber(res, "owning_tab"); + i_owning_col = PQfnumber(res, "owning_col"); + i_reltablespace = PQfnumber(res, "reltablespace"); + i_reloptions = PQfnumber(res, "reloptions"); + i_checkoption = PQfnumber(res, "checkoption"); + i_toastreloptions = PQfnumber(res, "toast_reloptions"); + i_reloftype = PQfnumber(res, "reloftype"); + i_is_identity_sequence = PQfnumber(res, "is_identity_sequence"); + i_changed_acl = PQfnumber(res, "changed_acl"); + i_partkeydef = PQfnumber(res, "partkeydef"); + i_ispartition = PQfnumber(res, "ispartition"); + i_partbound = PQfnumber(res, "partbound"); + i_amname = PQfnumber(res, "amname"); + + if (dopt->lockWaitTimeout) + { + /* + * Arrange to fail instead of waiting forever for a table lock. + * + * NB: this coding assumes that the only queries issued within the + * following loop are LOCK TABLEs; else the timeout may be undesirably + * applied to other things too. + */ + resetPQExpBuffer(query); + appendPQExpBufferStr(query, "SET statement_timeout = "); + appendStringLiteralConn(query, dopt->lockWaitTimeout, GetConnection(fout)); + ExecuteSqlStatement(fout, query->data); + } + + for (i = 0; i < ntups; i++) + { + tblinfo[i].dobj.objType = DO_TABLE; + tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid)); + tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid)); + AssignDumpId(&tblinfo[i].dobj); + tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname)); + tblinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_relnamespace))); + tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + tblinfo[i].relacl = pg_strdup(PQgetvalue(res, i, i_relacl)); + tblinfo[i].rrelacl = pg_strdup(PQgetvalue(res, i, i_rrelacl)); + tblinfo[i].initrelacl = pg_strdup(PQgetvalue(res, i, i_initrelacl)); + tblinfo[i].initrrelacl = pg_strdup(PQgetvalue(res, i, i_initrrelacl)); + tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind)); + tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence)); + tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0); + tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0); + tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0); + tblinfo[i].rowsec = (strcmp(PQgetvalue(res, i, i_relrowsec), "t") == 0); + tblinfo[i].forcerowsec = (strcmp(PQgetvalue(res, i, i_relforcerowsec), "t") == 0); + tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0); + tblinfo[i].relispopulated = (strcmp(PQgetvalue(res, i, i_relispopulated), "t") == 0); + tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident)); + tblinfo[i].relpages = atoi(PQgetvalue(res, i, i_relpages)); + tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid)); + tblinfo[i].minmxid = atooid(PQgetvalue(res, i, i_relminmxid)); + tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid)); + tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid)); + tblinfo[i].toast_minmxid = atooid(PQgetvalue(res, i, i_toastminmxid)); + if (PQgetisnull(res, i, i_reloftype)) + tblinfo[i].reloftype = NULL; + else + tblinfo[i].reloftype = pg_strdup(PQgetvalue(res, i, i_reloftype)); + tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks)); + if (PQgetisnull(res, i, i_owning_tab)) + { + tblinfo[i].owning_tab = InvalidOid; + tblinfo[i].owning_col = 0; + } + else + { + tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab)); + tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col)); + } + tblinfo[i].reltablespace = pg_strdup(PQgetvalue(res, i, i_reltablespace)); + tblinfo[i].reloptions = pg_strdup(PQgetvalue(res, i, i_reloptions)); + if (i_checkoption == -1 || PQgetisnull(res, i, i_checkoption)) + tblinfo[i].checkoption = NULL; + else + tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption)); + tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions)); + if (PQgetisnull(res, i, i_amname)) + tblinfo[i].amname = NULL; + else + tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname)); + + /* other fields were zeroed above */ + + /* + * Decide whether we want to dump this table. + */ + if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE) + tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE; + else + selectDumpableTable(&tblinfo[i], fout); + + /* + * If the table-level and all column-level ACLs for this table are + * unchanged, then we don't need to worry about including the ACLs for + * this table. If any column-level ACLs have been changed, the + * 'changed_acl' column from the query will indicate that. + * + * This can result in a significant performance improvement in cases + * where we are only looking to dump out the ACL (eg: pg_catalog). + */ + if (PQgetisnull(res, i, i_relacl) && PQgetisnull(res, i, i_rrelacl) && + PQgetisnull(res, i, i_initrelacl) && + PQgetisnull(res, i, i_initrrelacl) && + strcmp(PQgetvalue(res, i, i_changed_acl), "f") == 0) + tblinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + + tblinfo[i].interesting = tblinfo[i].dobj.dump ? true : false; + tblinfo[i].dummy_view = false; /* might get set during sort */ + tblinfo[i].postponed_def = false; /* might get set during sort */ + + tblinfo[i].is_identity_sequence = (i_is_identity_sequence >= 0 && + strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0); + + /* Partition key string or NULL */ + tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, i_partkeydef)); + tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0); + tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound)); + + /* foreign server */ + tblinfo[i].foreign_server = atooid(PQgetvalue(res, i, i_foreignserver)); + + /* + * Read-lock target tables to make sure they aren't DROPPED or altered + * in schema before we get around to dumping them. + * + * Note that we don't explicitly lock parents of the target tables; we + * assume our lock on the child is enough to prevent schema + * alterations to parent tables. + * + * NOTE: it'd be kinda nice to lock other relations too, not only + * plain or partitioned tables, but the backend doesn't presently + * allow that. + * + * We only need to lock the table for certain components; see + * pg_dump.h + */ + if (tblinfo[i].dobj.dump && + (tblinfo[i].relkind == RELKIND_RELATION || + tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE) && + (tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK)) + { + resetPQExpBuffer(query); + appendPQExpBuffer(query, + "LOCK TABLE %s IN ACCESS SHARE MODE", + fmtQualifiedDumpable(&tblinfo[i])); + ExecuteSqlStatement(fout, query->data); + } + + /* Emit notice if join for owner failed */ + if (strlen(tblinfo[i].rolname) == 0) + pg_log_warning("owner of table \"%s\" appears to be invalid", + tblinfo[i].dobj.name); + } + + if (dopt->lockWaitTimeout) + { + ExecuteSqlStatement(fout, "SET statement_timeout = 0"); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return tblinfo; +} + +/* + * getOwnedSeqs + * identify owned sequences and mark them as dumpable if owning table is + * + * We used to do this in getTables(), but it's better to do it after the + * index used by findTableByOid() has been set up. + */ +void +getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i; + + /* + * Force sequences that are "owned" by table columns to be dumped whenever + * their owning table is being dumped. + */ + for (i = 0; i < numTables; i++) + { + TableInfo *seqinfo = &tblinfo[i]; + TableInfo *owning_tab; + + if (!OidIsValid(seqinfo->owning_tab)) + continue; /* not an owned sequence */ + + owning_tab = findTableByOid(seqinfo->owning_tab); + if (owning_tab == NULL) + fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found", + seqinfo->owning_tab, seqinfo->dobj.catId.oid); + + /* + * Only dump identity sequences if we're going to dump the table that + * it belongs to. + */ + if (owning_tab->dobj.dump == DUMP_COMPONENT_NONE && + seqinfo->is_identity_sequence) + { + seqinfo->dobj.dump = DUMP_COMPONENT_NONE; + continue; + } + + /* + * Otherwise we need to dump the components that are being dumped for + * the table and any components which the sequence is explicitly + * marked with. + * + * We can't simply use the set of components which are being dumped + * for the table as the table might be in an extension (and only the + * non-extension components, eg: ACLs if changed, security labels, and + * policies, are being dumped) while the sequence is not (and + * therefore the definition and other components should also be + * dumped). + * + * If the sequence is part of the extension then it should be properly + * marked by checkExtensionMembership() and this will be a no-op as + * the table will be equivalently marked. + */ + seqinfo->dobj.dump = seqinfo->dobj.dump | owning_tab->dobj.dump; + + if (seqinfo->dobj.dump != DUMP_COMPONENT_NONE) + seqinfo->interesting = true; + } +} + +/* + * getInherits + * read all the inheritance information + * from the system catalogs return them in the InhInfo* structure + * + * numInherits is set to the number of pairs read in + */ +InhInfo * +getInherits(Archive *fout, int *numInherits) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + InhInfo *inhinfo; + + int i_inhrelid; + int i_inhparent; + + /* find all the inheritance information */ + appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numInherits = ntups; + + inhinfo = (InhInfo *) pg_malloc(ntups * sizeof(InhInfo)); + + i_inhrelid = PQfnumber(res, "inhrelid"); + i_inhparent = PQfnumber(res, "inhparent"); + + for (i = 0; i < ntups; i++) + { + inhinfo[i].inhrelid = atooid(PQgetvalue(res, i, i_inhrelid)); + inhinfo[i].inhparent = atooid(PQgetvalue(res, i, i_inhparent)); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return inhinfo; +} + +/* + * getIndexes + * get information about every index on a dumpable table + * + * Note: index data is not returned directly to the caller, but it + * does get entered into the DumpableObject tables. + */ +void +getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i, + j; + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + IndxInfo *indxinfo; + ConstraintInfo *constrinfo; + int i_tableoid, + i_oid, + i_indexname, + i_parentidx, + i_indexdef, + i_indnkeyatts, + i_indnatts, + i_indkey, + i_indisclustered, + i_indisreplident, + i_contype, + i_conname, + i_condeferrable, + i_condeferred, + i_contableoid, + i_conoid, + i_condef, + i_tablespace, + i_indreloptions, + i_indstatcols, + i_indstatvals; + int ntups; + + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &tblinfo[i]; + + if (!tbinfo->hasindex) + continue; + + /* + * Ignore indexes of tables whose definitions are not to be dumped. + * + * We also need indexes on partitioned tables which have partitions to + * be dumped, in order to dump the indexes on the partitions. + */ + if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) && + !tbinfo->interesting) + continue; + + pg_log_info("reading indexes for table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + /* + * The point of the messy-looking outer join is to find a constraint + * that is related by an internal dependency link to the index. If we + * find one, create a CONSTRAINT entry linked to the INDEX entry. We + * assume an index won't have more than one internal dependency. + * + * As of 9.0 we don't need to look at pg_depend but can check for a + * match to pg_constraint.conindid. The check on conrelid is + * redundant but useful because that column is indexed while conindid + * is not. + */ + resetPQExpBuffer(query); + if (fout->remoteVersion >= 110000) + { + appendPQExpBuffer(query, + "SELECT t.tableoid, t.oid, " + "t.relname AS indexname, " + "inh.inhparent AS parentidx, " + "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " + "i.indnkeyatts AS indnkeyatts, " + "i.indnatts AS indnatts, " + "i.indkey, i.indisclustered, " + "i.indisreplident, " + "c.contype, c.conname, " + "c.condeferrable, c.condeferred, " + "c.tableoid AS contableoid, " + "c.oid AS conoid, " + "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, " + "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " + "t.reloptions AS indreloptions, " + "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) " + " FROM pg_catalog.pg_attribute " + " WHERE attrelid = i.indexrelid AND " + " attstattarget >= 0) AS indstatcols," + "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) " + " FROM pg_catalog.pg_attribute " + " WHERE attrelid = i.indexrelid AND " + " attstattarget >= 0) AS indstatvals " + "FROM pg_catalog.pg_index i " + "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) " + "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) " + "LEFT JOIN pg_catalog.pg_constraint c " + "ON (i.indrelid = c.conrelid AND " + "i.indexrelid = c.conindid AND " + "c.contype IN ('p','u','x')) " + "LEFT JOIN pg_catalog.pg_inherits inh " + "ON (inh.inhrelid = indexrelid) " + "WHERE i.indrelid = '%u'::pg_catalog.oid " + "AND (i.indisvalid OR t2.relkind = 'p') " + "AND i.indisready " + "ORDER BY indexname", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 90400) + { + /* + * the test on indisready is necessary in 9.2, and harmless in + * earlier/later versions + */ + appendPQExpBuffer(query, + "SELECT t.tableoid, t.oid, " + "t.relname AS indexname, " + "0 AS parentidx, " + "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " + "i.indnatts AS indnkeyatts, " + "i.indnatts AS indnatts, " + "i.indkey, i.indisclustered, " + "i.indisreplident, " + "c.contype, c.conname, " + "c.condeferrable, c.condeferred, " + "c.tableoid AS contableoid, " + "c.oid AS conoid, " + "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, " + "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " + "t.reloptions AS indreloptions, " + "'' AS indstatcols, " + "'' AS indstatvals " + "FROM pg_catalog.pg_index i " + "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) " + "LEFT JOIN pg_catalog.pg_constraint c " + "ON (i.indrelid = c.conrelid AND " + "i.indexrelid = c.conindid AND " + "c.contype IN ('p','u','x')) " + "WHERE i.indrelid = '%u'::pg_catalog.oid " + "AND i.indisvalid AND i.indisready " + "ORDER BY indexname", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 90000) + { + /* + * the test on indisready is necessary in 9.2, and harmless in + * earlier/later versions + */ + appendPQExpBuffer(query, + "SELECT t.tableoid, t.oid, " + "t.relname AS indexname, " + "0 AS parentidx, " + "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " + "i.indnatts AS indnkeyatts, " + "i.indnatts AS indnatts, " + "i.indkey, i.indisclustered, " + "false AS indisreplident, " + "c.contype, c.conname, " + "c.condeferrable, c.condeferred, " + "c.tableoid AS contableoid, " + "c.oid AS conoid, " + "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, " + "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " + "t.reloptions AS indreloptions, " + "'' AS indstatcols, " + "'' AS indstatvals " + "FROM pg_catalog.pg_index i " + "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) " + "LEFT JOIN pg_catalog.pg_constraint c " + "ON (i.indrelid = c.conrelid AND " + "i.indexrelid = c.conindid AND " + "c.contype IN ('p','u','x')) " + "WHERE i.indrelid = '%u'::pg_catalog.oid " + "AND i.indisvalid AND i.indisready " + "ORDER BY indexname", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80200) + { + appendPQExpBuffer(query, + "SELECT t.tableoid, t.oid, " + "t.relname AS indexname, " + "0 AS parentidx, " + "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " + "i.indnatts AS indnkeyatts, " + "i.indnatts AS indnatts, " + "i.indkey, i.indisclustered, " + "false AS indisreplident, " + "c.contype, c.conname, " + "c.condeferrable, c.condeferred, " + "c.tableoid AS contableoid, " + "c.oid AS conoid, " + "null AS condef, " + "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " + "t.reloptions AS indreloptions, " + "'' AS indstatcols, " + "'' AS indstatvals " + "FROM pg_catalog.pg_index i " + "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) " + "LEFT JOIN pg_catalog.pg_depend d " + "ON (d.classid = t.tableoid " + "AND d.objid = t.oid " + "AND d.deptype = 'i') " + "LEFT JOIN pg_catalog.pg_constraint c " + "ON (d.refclassid = c.tableoid " + "AND d.refobjid = c.oid) " + "WHERE i.indrelid = '%u'::pg_catalog.oid " + "AND i.indisvalid " + "ORDER BY indexname", + tbinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, + "SELECT t.tableoid, t.oid, " + "t.relname AS indexname, " + "0 AS parentidx, " + "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " + "t.relnatts AS indnkeyatts, " + "t.relnatts AS indnatts, " + "i.indkey, i.indisclustered, " + "false AS indisreplident, " + "c.contype, c.conname, " + "c.condeferrable, c.condeferred, " + "c.tableoid AS contableoid, " + "c.oid AS conoid, " + "null AS condef, " + "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " + "null AS indreloptions, " + "'' AS indstatcols, " + "'' AS indstatvals " + "FROM pg_catalog.pg_index i " + "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) " + "LEFT JOIN pg_catalog.pg_depend d " + "ON (d.classid = t.tableoid " + "AND d.objid = t.oid " + "AND d.deptype = 'i') " + "LEFT JOIN pg_catalog.pg_constraint c " + "ON (d.refclassid = c.tableoid " + "AND d.refobjid = c.oid) " + "WHERE i.indrelid = '%u'::pg_catalog.oid " + "ORDER BY indexname", + tbinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_indexname = PQfnumber(res, "indexname"); + i_parentidx = PQfnumber(res, "parentidx"); + i_indexdef = PQfnumber(res, "indexdef"); + i_indnkeyatts = PQfnumber(res, "indnkeyatts"); + i_indnatts = PQfnumber(res, "indnatts"); + i_indkey = PQfnumber(res, "indkey"); + i_indisclustered = PQfnumber(res, "indisclustered"); + i_indisreplident = PQfnumber(res, "indisreplident"); + i_contype = PQfnumber(res, "contype"); + i_conname = PQfnumber(res, "conname"); + i_condeferrable = PQfnumber(res, "condeferrable"); + i_condeferred = PQfnumber(res, "condeferred"); + i_contableoid = PQfnumber(res, "contableoid"); + i_conoid = PQfnumber(res, "conoid"); + i_condef = PQfnumber(res, "condef"); + i_tablespace = PQfnumber(res, "tablespace"); + i_indreloptions = PQfnumber(res, "indreloptions"); + i_indstatcols = PQfnumber(res, "indstatcols"); + i_indstatvals = PQfnumber(res, "indstatvals"); + + tbinfo->indexes = indxinfo = + (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo)); + constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo)); + tbinfo->numIndexes = ntups; + + for (j = 0; j < ntups; j++) + { + char contype; + + indxinfo[j].dobj.objType = DO_INDEX; + indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid)); + indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); + AssignDumpId(&indxinfo[j].dobj); + indxinfo[j].dobj.dump = tbinfo->dobj.dump; + indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname)); + indxinfo[j].dobj.namespace = tbinfo->dobj.namespace; + indxinfo[j].indextable = tbinfo; + indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef)); + indxinfo[j].indnkeyattrs = atoi(PQgetvalue(res, j, i_indnkeyatts)); + indxinfo[j].indnattrs = atoi(PQgetvalue(res, j, i_indnatts)); + indxinfo[j].tablespace = pg_strdup(PQgetvalue(res, j, i_tablespace)); + indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions)); + indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols)); + indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals)); + indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid)); + parseOidArray(PQgetvalue(res, j, i_indkey), + indxinfo[j].indkeys, indxinfo[j].indnattrs); + indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't'); + indxinfo[j].indisreplident = (PQgetvalue(res, j, i_indisreplident)[0] == 't'); + indxinfo[j].parentidx = atooid(PQgetvalue(res, j, i_parentidx)); + indxinfo[j].partattaches = (SimplePtrList) + { + NULL, NULL + }; + contype = *(PQgetvalue(res, j, i_contype)); + + if (contype == 'p' || contype == 'u' || contype == 'x') + { + /* + * If we found a constraint matching the index, create an + * entry for it. + */ + constrinfo[j].dobj.objType = DO_CONSTRAINT; + constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid)); + constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid)); + AssignDumpId(&constrinfo[j].dobj); + constrinfo[j].dobj.dump = tbinfo->dobj.dump; + constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname)); + constrinfo[j].dobj.namespace = tbinfo->dobj.namespace; + constrinfo[j].contable = tbinfo; + constrinfo[j].condomain = NULL; + constrinfo[j].contype = contype; + if (contype == 'x') + constrinfo[j].condef = pg_strdup(PQgetvalue(res, j, i_condef)); + else + constrinfo[j].condef = NULL; + constrinfo[j].confrelid = InvalidOid; + constrinfo[j].conindex = indxinfo[j].dobj.dumpId; + constrinfo[j].condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't'; + constrinfo[j].condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't'; + constrinfo[j].conislocal = true; + constrinfo[j].separate = true; + + indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId; + } + else + { + /* Plain secondary index */ + indxinfo[j].indexconstraint = 0; + } + } + + PQclear(res); + } + + destroyPQExpBuffer(query); +} + +/* + * getExtendedStatistics + * get information about extended-statistics objects. + * + * Note: extended statistics data is not returned directly to the caller, but + * it does get entered into the DumpableObject tables. + */ +void +getExtendedStatistics(Archive *fout) +{ + PQExpBuffer query; + PGresult *res; + StatsExtInfo *statsextinfo; + int ntups; + int i_tableoid; + int i_oid; + int i_stxname; + int i_stxnamespace; + int i_rolname; + int i_stattarget; + int i; + + /* Extended statistics were new in v10 */ + if (fout->remoteVersion < 100000) + return; + + query = createPQExpBuffer(); + + if (fout->remoteVersion < 130000) + appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, " + "stxnamespace, (%s stxowner) AS rolname, (-1) AS stxstattarget " + "FROM pg_catalog.pg_statistic_ext", + username_subquery); + else + appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, " + "stxnamespace, (%s stxowner) AS rolname, stxstattarget " + "FROM pg_catalog.pg_statistic_ext", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_stxname = PQfnumber(res, "stxname"); + i_stxnamespace = PQfnumber(res, "stxnamespace"); + i_rolname = PQfnumber(res, "rolname"); + i_stattarget = PQfnumber(res, "stxstattarget"); + + statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo)); + + for (i = 0; i < ntups; i++) + { + statsextinfo[i].dobj.objType = DO_STATSEXT; + statsextinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + statsextinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&statsextinfo[i].dobj); + statsextinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_stxname)); + statsextinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_stxnamespace))); + statsextinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(statsextinfo[i].dobj), fout); + + /* Stats objects do not currently have ACLs. */ + statsextinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + destroyPQExpBuffer(query); +} + +/* + * getConstraints + * + * Get info about constraints on dumpable tables. + * + * Currently handles foreign keys only. + * Unique and primary key constraints are handled with indexes, + * while check constraints are processed in getTableAttrs(). + */ +void +getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i, + j; + ConstraintInfo *constrinfo; + PQExpBuffer query; + PGresult *res; + int i_contableoid, + i_conoid, + i_conname, + i_confrelid, + i_conindid, + i_condef; + int ntups; + + query = createPQExpBuffer(); + + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &tblinfo[i]; + + /* + * For partitioned tables, foreign keys have no triggers so they must + * be included anyway in case some foreign keys are defined. + */ + if ((!tbinfo->hastriggers && + tbinfo->relkind != RELKIND_PARTITIONED_TABLE) || + !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + continue; + + pg_log_info("reading foreign key constraints for table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + resetPQExpBuffer(query); + if (fout->remoteVersion >= 110000) + appendPQExpBuffer(query, + "SELECT tableoid, oid, conname, confrelid, conindid, " + "pg_catalog.pg_get_constraintdef(oid) AS condef " + "FROM pg_catalog.pg_constraint " + "WHERE conrelid = '%u'::pg_catalog.oid " + "AND conparentid = 0 " + "AND contype = 'f'", + tbinfo->dobj.catId.oid); + else + appendPQExpBuffer(query, + "SELECT tableoid, oid, conname, confrelid, 0 as conindid, " + "pg_catalog.pg_get_constraintdef(oid) AS condef " + "FROM pg_catalog.pg_constraint " + "WHERE conrelid = '%u'::pg_catalog.oid " + "AND contype = 'f'", + tbinfo->dobj.catId.oid); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_contableoid = PQfnumber(res, "tableoid"); + i_conoid = PQfnumber(res, "oid"); + i_conname = PQfnumber(res, "conname"); + i_confrelid = PQfnumber(res, "confrelid"); + i_conindid = PQfnumber(res, "conindid"); + i_condef = PQfnumber(res, "condef"); + + constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo)); + + for (j = 0; j < ntups; j++) + { + TableInfo *reftable; + + constrinfo[j].dobj.objType = DO_FK_CONSTRAINT; + constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid)); + constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid)); + AssignDumpId(&constrinfo[j].dobj); + constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname)); + constrinfo[j].dobj.namespace = tbinfo->dobj.namespace; + constrinfo[j].contable = tbinfo; + constrinfo[j].condomain = NULL; + constrinfo[j].contype = 'f'; + constrinfo[j].condef = pg_strdup(PQgetvalue(res, j, i_condef)); + constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid)); + constrinfo[j].conindex = 0; + constrinfo[j].condeferrable = false; + constrinfo[j].condeferred = false; + constrinfo[j].conislocal = true; + constrinfo[j].separate = true; + + /* + * Restoring an FK that points to a partitioned table requires + * that all partition indexes have been attached beforehand. + * Ensure that happens by making the constraint depend on each + * index partition attach object. + */ + reftable = findTableByOid(constrinfo[j].confrelid); + if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE) + { + Oid indexOid = atooid(PQgetvalue(res, j, i_conindid)); + + if (indexOid != InvalidOid) + { + for (int k = 0; k < reftable->numIndexes; k++) + { + IndxInfo *refidx; + + /* not our index? */ + if (reftable->indexes[k].dobj.catId.oid != indexOid) + continue; + + refidx = &reftable->indexes[k]; + addConstrChildIdxDeps(&constrinfo[j].dobj, refidx); + break; + } + } + } + } + + PQclear(res); + } + + destroyPQExpBuffer(query); +} + +/* + * addConstrChildIdxDeps + * + * Recursive subroutine for getConstraints + * + * Given an object representing a foreign key constraint and an index on the + * partitioned table it references, mark the constraint object as dependent + * on the DO_INDEX_ATTACH object of each index partition, recursively + * drilling down to their partitions if any. This ensures that the FK is not + * restored until the index is fully marked valid. + */ +static void +addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx) +{ + SimplePtrListCell *cell; + + Assert(dobj->objType == DO_FK_CONSTRAINT); + + for (cell = refidx->partattaches.head; cell; cell = cell->next) + { + IndexAttachInfo *attach = (IndexAttachInfo *) cell->ptr; + + addObjectDependency(dobj, attach->dobj.dumpId); + + if (attach->partitionIdx->partattaches.head != NULL) + addConstrChildIdxDeps(dobj, attach->partitionIdx); + } +} + +/* + * getDomainConstraints + * + * Get info about constraints on a domain. + */ +static void +getDomainConstraints(Archive *fout, TypeInfo *tyinfo) +{ + int i; + ConstraintInfo *constrinfo; + PQExpBuffer query; + PGresult *res; + int i_tableoid, + i_oid, + i_conname, + i_consrc; + int ntups; + + query = createPQExpBuffer(); + + if (fout->remoteVersion >= 90100) + appendPQExpBuffer(query, "SELECT tableoid, oid, conname, " + "pg_catalog.pg_get_constraintdef(oid) AS consrc, " + "convalidated " + "FROM pg_catalog.pg_constraint " + "WHERE contypid = '%u'::pg_catalog.oid " + "ORDER BY conname", + tyinfo->dobj.catId.oid); + + else + appendPQExpBuffer(query, "SELECT tableoid, oid, conname, " + "pg_catalog.pg_get_constraintdef(oid) AS consrc, " + "true as convalidated " + "FROM pg_catalog.pg_constraint " + "WHERE contypid = '%u'::pg_catalog.oid " + "ORDER BY conname", + tyinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_conname = PQfnumber(res, "conname"); + i_consrc = PQfnumber(res, "consrc"); + + constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo)); + + tyinfo->nDomChecks = ntups; + tyinfo->domChecks = constrinfo; + + for (i = 0; i < ntups; i++) + { + bool validated = PQgetvalue(res, i, 4)[0] == 't'; + + constrinfo[i].dobj.objType = DO_CONSTRAINT; + constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&constrinfo[i].dobj); + constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname)); + constrinfo[i].dobj.namespace = tyinfo->dobj.namespace; + constrinfo[i].contable = NULL; + constrinfo[i].condomain = tyinfo; + constrinfo[i].contype = 'c'; + constrinfo[i].condef = pg_strdup(PQgetvalue(res, i, i_consrc)); + constrinfo[i].confrelid = InvalidOid; + constrinfo[i].conindex = 0; + constrinfo[i].condeferrable = false; + constrinfo[i].condeferred = false; + constrinfo[i].conislocal = true; + + constrinfo[i].separate = !validated; + + /* + * Make the domain depend on the constraint, ensuring it won't be + * output till any constraint dependencies are OK. If the constraint + * has not been validated, it's going to be dumped after the domain + * anyway, so this doesn't matter. + */ + if (validated) + addObjectDependency(&tyinfo->dobj, + constrinfo[i].dobj.dumpId); + } + + PQclear(res); + + destroyPQExpBuffer(query); +} + +/* + * getRules + * get basic information about every rule in the system + * + * numRules is set to the number of rules read in + */ +RuleInfo * +getRules(Archive *fout, int *numRules) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + RuleInfo *ruleinfo; + int i_tableoid; + int i_oid; + int i_rulename; + int i_ruletable; + int i_ev_type; + int i_is_instead; + int i_ev_enabled; + + if (fout->remoteVersion >= 80300) + { + appendPQExpBufferStr(query, "SELECT " + "tableoid, oid, rulename, " + "ev_class AS ruletable, ev_type, is_instead, " + "ev_enabled " + "FROM pg_rewrite " + "ORDER BY oid"); + } + else + { + appendPQExpBufferStr(query, "SELECT " + "tableoid, oid, rulename, " + "ev_class AS ruletable, ev_type, is_instead, " + "'O'::char AS ev_enabled " + "FROM pg_rewrite " + "ORDER BY oid"); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numRules = ntups; + + ruleinfo = (RuleInfo *) pg_malloc(ntups * sizeof(RuleInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_rulename = PQfnumber(res, "rulename"); + i_ruletable = PQfnumber(res, "ruletable"); + i_ev_type = PQfnumber(res, "ev_type"); + i_is_instead = PQfnumber(res, "is_instead"); + i_ev_enabled = PQfnumber(res, "ev_enabled"); + + for (i = 0; i < ntups; i++) + { + Oid ruletableoid; + + ruleinfo[i].dobj.objType = DO_RULE; + ruleinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&ruleinfo[i].dobj); + ruleinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_rulename)); + ruletableoid = atooid(PQgetvalue(res, i, i_ruletable)); + ruleinfo[i].ruletable = findTableByOid(ruletableoid); + if (ruleinfo[i].ruletable == NULL) + fatal("failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found", + ruletableoid, ruleinfo[i].dobj.catId.oid); + ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace; + ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump; + ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type)); + ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't'; + ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled)); + if (ruleinfo[i].ruletable) + { + /* + * If the table is a view or materialized view, force its ON + * SELECT rule to be sorted before the view itself --- this + * ensures that any dependencies for the rule affect the table's + * positioning. Other rules are forced to appear after their + * table. + */ + if ((ruleinfo[i].ruletable->relkind == RELKIND_VIEW || + ruleinfo[i].ruletable->relkind == RELKIND_MATVIEW) && + ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead) + { + addObjectDependency(&ruleinfo[i].ruletable->dobj, + ruleinfo[i].dobj.dumpId); + /* We'll merge the rule into CREATE VIEW, if possible */ + ruleinfo[i].separate = false; + } + else + { + addObjectDependency(&ruleinfo[i].dobj, + ruleinfo[i].ruletable->dobj.dumpId); + ruleinfo[i].separate = true; + } + } + else + ruleinfo[i].separate = true; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return ruleinfo; +} + +/* + * getTriggers + * get information about every trigger on a dumpable table + * + * Note: trigger data is not returned directly to the caller, but it + * does get entered into the DumpableObject tables. + */ +void +getTriggers(Archive *fout, TableInfo tblinfo[], int numTables) +{ + int i, + j; + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + TriggerInfo *tginfo; + int i_tableoid, + i_oid, + i_tgname, + i_tgfname, + i_tgtype, + i_tgnargs, + i_tgargs, + i_tgisconstraint, + i_tgconstrname, + i_tgconstrrelid, + i_tgconstrrelname, + i_tgenabled, + i_tgisinternal, + i_tgdeferrable, + i_tginitdeferred, + i_tgdef; + int ntups; + + for (i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &tblinfo[i]; + + if (!tbinfo->hastriggers || + !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + continue; + + pg_log_info("reading triggers for table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + resetPQExpBuffer(query); + if (fout->remoteVersion >= 130000) + { + /* + * NB: think not to use pretty=true in pg_get_triggerdef. It + * could result in non-forward-compatible dumps of WHEN clauses + * due to under-parenthesization. + * + * NB: We need to see tgisinternal triggers in partitions, in case + * the tgenabled flag has been changed from the parent. + */ + appendPQExpBuffer(query, + "SELECT t.tgname, " + "t.tgfoid::pg_catalog.regproc AS tgfname, " + "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, " + "t.tgenabled, t.tableoid, t.oid, t.tgisinternal " + "FROM pg_catalog.pg_trigger t " + "LEFT JOIN pg_catalog.pg_trigger u ON u.oid = t.tgparentid " + "WHERE t.tgrelid = '%u'::pg_catalog.oid " + "AND (NOT t.tgisinternal OR t.tgenabled != u.tgenabled)", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 110000) + { + /* + * NB: We need to see tgisinternal triggers in partitions, in case + * the tgenabled flag has been changed from the parent. No + * tgparentid in version 11-12, so we have to match them via + * pg_depend. + * + * See above about pretty=true in pg_get_triggerdef. + */ + appendPQExpBuffer(query, + "SELECT t.tgname, " + "t.tgfoid::pg_catalog.regproc AS tgfname, " + "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, " + "t.tgenabled, t.tableoid, t.oid, t.tgisinternal " + "FROM pg_catalog.pg_trigger t " + "LEFT JOIN pg_catalog.pg_depend AS d ON " + " d.classid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND " + " d.refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND " + " d.objid = t.oid " + "LEFT JOIN pg_catalog.pg_trigger AS pt ON pt.oid = refobjid " + "WHERE t.tgrelid = '%u'::pg_catalog.oid " + "AND (NOT t.tgisinternal%s)", + tbinfo->dobj.catId.oid, + tbinfo->ispartition ? + " OR t.tgenabled != pt.tgenabled" : ""); + } + else if (fout->remoteVersion >= 90000) + { + /* See above about pretty=true in pg_get_triggerdef */ + appendPQExpBuffer(query, + "SELECT t.tgname, " + "t.tgfoid::pg_catalog.regproc AS tgfname, " + "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, " + "t.tgenabled, false as tgisinternal, " + "t.tableoid, t.oid " + "FROM pg_catalog.pg_trigger t " + "WHERE tgrelid = '%u'::pg_catalog.oid " + "AND NOT tgisinternal", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80300) + { + /* + * We ignore triggers that are tied to a foreign-key constraint + */ + appendPQExpBuffer(query, + "SELECT tgname, " + "tgfoid::pg_catalog.regproc AS tgfname, " + "tgtype, tgnargs, tgargs, tgenabled, " + "false as tgisinternal, " + "tgisconstraint, tgconstrname, tgdeferrable, " + "tgconstrrelid, tginitdeferred, tableoid, oid, " + "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname " + "FROM pg_catalog.pg_trigger t " + "WHERE tgrelid = '%u'::pg_catalog.oid " + "AND tgconstraint = 0", + tbinfo->dobj.catId.oid); + } + else + { + /* + * We ignore triggers that are tied to a foreign-key constraint, + * but in these versions we have to grovel through pg_constraint + * to find out + */ + appendPQExpBuffer(query, + "SELECT tgname, " + "tgfoid::pg_catalog.regproc AS tgfname, " + "tgtype, tgnargs, tgargs, tgenabled, " + "false as tgisinternal, " + "tgisconstraint, tgconstrname, tgdeferrable, " + "tgconstrrelid, tginitdeferred, tableoid, oid, " + "tgconstrrelid::pg_catalog.regclass AS tgconstrrelname " + "FROM pg_catalog.pg_trigger t " + "WHERE tgrelid = '%u'::pg_catalog.oid " + "AND (NOT tgisconstraint " + " OR NOT EXISTS" + " (SELECT 1 FROM pg_catalog.pg_depend d " + " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) " + " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))", + tbinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_tgname = PQfnumber(res, "tgname"); + i_tgfname = PQfnumber(res, "tgfname"); + i_tgtype = PQfnumber(res, "tgtype"); + i_tgnargs = PQfnumber(res, "tgnargs"); + i_tgargs = PQfnumber(res, "tgargs"); + i_tgisconstraint = PQfnumber(res, "tgisconstraint"); + i_tgconstrname = PQfnumber(res, "tgconstrname"); + i_tgconstrrelid = PQfnumber(res, "tgconstrrelid"); + i_tgconstrrelname = PQfnumber(res, "tgconstrrelname"); + i_tgenabled = PQfnumber(res, "tgenabled"); + i_tgisinternal = PQfnumber(res, "tgisinternal"); + i_tgdeferrable = PQfnumber(res, "tgdeferrable"); + i_tginitdeferred = PQfnumber(res, "tginitdeferred"); + i_tgdef = PQfnumber(res, "tgdef"); + + tginfo = (TriggerInfo *) pg_malloc(ntups * sizeof(TriggerInfo)); + + tbinfo->numTriggers = ntups; + tbinfo->triggers = tginfo; + + for (j = 0; j < ntups; j++) + { + tginfo[j].dobj.objType = DO_TRIGGER; + tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid)); + tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); + AssignDumpId(&tginfo[j].dobj); + tginfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_tgname)); + tginfo[j].dobj.namespace = tbinfo->dobj.namespace; + tginfo[j].tgtable = tbinfo; + tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled)); + tginfo[j].tgisinternal = *(PQgetvalue(res, j, i_tgisinternal)) == 't'; + if (i_tgdef >= 0) + { + tginfo[j].tgdef = pg_strdup(PQgetvalue(res, j, i_tgdef)); + + /* remaining fields are not valid if we have tgdef */ + tginfo[j].tgfname = NULL; + tginfo[j].tgtype = 0; + tginfo[j].tgnargs = 0; + tginfo[j].tgargs = NULL; + tginfo[j].tgisconstraint = false; + tginfo[j].tgdeferrable = false; + tginfo[j].tginitdeferred = false; + tginfo[j].tgconstrname = NULL; + tginfo[j].tgconstrrelid = InvalidOid; + tginfo[j].tgconstrrelname = NULL; + } + else + { + tginfo[j].tgdef = NULL; + + tginfo[j].tgfname = pg_strdup(PQgetvalue(res, j, i_tgfname)); + tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype)); + tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs)); + tginfo[j].tgargs = pg_strdup(PQgetvalue(res, j, i_tgargs)); + tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't'; + tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't'; + tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't'; + + if (tginfo[j].tgisconstraint) + { + tginfo[j].tgconstrname = pg_strdup(PQgetvalue(res, j, i_tgconstrname)); + tginfo[j].tgconstrrelid = atooid(PQgetvalue(res, j, i_tgconstrrelid)); + if (OidIsValid(tginfo[j].tgconstrrelid)) + { + if (PQgetisnull(res, j, i_tgconstrrelname)) + fatal("query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)", + tginfo[j].dobj.name, + tbinfo->dobj.name, + tginfo[j].tgconstrrelid); + tginfo[j].tgconstrrelname = pg_strdup(PQgetvalue(res, j, i_tgconstrrelname)); + } + else + tginfo[j].tgconstrrelname = NULL; + } + else + { + tginfo[j].tgconstrname = NULL; + tginfo[j].tgconstrrelid = InvalidOid; + tginfo[j].tgconstrrelname = NULL; + } + } + } + + PQclear(res); + } + + destroyPQExpBuffer(query); +} + +/* + * getEventTriggers + * get information about event triggers + */ +EventTriggerInfo * +getEventTriggers(Archive *fout, int *numEventTriggers) +{ + int i; + PQExpBuffer query; + PGresult *res; + EventTriggerInfo *evtinfo; + int i_tableoid, + i_oid, + i_evtname, + i_evtevent, + i_evtowner, + i_evttags, + i_evtfname, + i_evtenabled; + int ntups; + + /* Before 9.3, there are no event triggers */ + if (fout->remoteVersion < 90300) + { + *numEventTriggers = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBuffer(query, + "SELECT e.tableoid, e.oid, evtname, evtenabled, " + "evtevent, (%s evtowner) AS evtowner, " + "array_to_string(array(" + "select quote_literal(x) " + " from unnest(evttags) as t(x)), ', ') as evttags, " + "e.evtfoid::regproc as evtfname " + "FROM pg_event_trigger e " + "ORDER BY e.oid", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numEventTriggers = ntups; + + evtinfo = (EventTriggerInfo *) pg_malloc(ntups * sizeof(EventTriggerInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_evtname = PQfnumber(res, "evtname"); + i_evtevent = PQfnumber(res, "evtevent"); + i_evtowner = PQfnumber(res, "evtowner"); + i_evttags = PQfnumber(res, "evttags"); + i_evtfname = PQfnumber(res, "evtfname"); + i_evtenabled = PQfnumber(res, "evtenabled"); + + for (i = 0; i < ntups; i++) + { + evtinfo[i].dobj.objType = DO_EVENT_TRIGGER; + evtinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + evtinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&evtinfo[i].dobj); + evtinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_evtname)); + evtinfo[i].evtname = pg_strdup(PQgetvalue(res, i, i_evtname)); + evtinfo[i].evtevent = pg_strdup(PQgetvalue(res, i, i_evtevent)); + evtinfo[i].evtowner = pg_strdup(PQgetvalue(res, i, i_evtowner)); + evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags)); + evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname)); + evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(evtinfo[i].dobj), fout); + + /* Event Triggers do not currently have ACLs. */ + evtinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return evtinfo; +} + +/* + * getProcLangs + * get basic information about every procedural language in the system + * + * numProcLangs is set to the number of langs read in + * + * NB: this must run after getFuncs() because we assume we can do + * findFuncByOid(). + */ +ProcLangInfo * +getProcLangs(Archive *fout, int *numProcLangs) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + ProcLangInfo *planginfo; + int i_tableoid; + int i_oid; + int i_lanname; + int i_lanpltrusted; + int i_lanplcallfoid; + int i_laninline; + int i_lanvalidator; + int i_lanacl; + int i_rlanacl; + int i_initlanacl; + int i_initrlanacl; + int i_lanowner; + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "l.lanacl", "l.lanowner", "'l'", + dopt->binary_upgrade); + + /* pg_language has a laninline column */ + appendPQExpBuffer(query, "SELECT l.tableoid, l.oid, " + "l.lanname, l.lanpltrusted, l.lanplcallfoid, " + "l.laninline, l.lanvalidator, " + "%s AS lanacl, " + "%s AS rlanacl, " + "%s AS initlanacl, " + "%s AS initrlanacl, " + "(%s l.lanowner) AS lanowner " + "FROM pg_language l " + "LEFT JOIN pg_init_privs pip ON " + "(l.oid = pip.objoid " + "AND pip.classoid = 'pg_language'::regclass " + "AND pip.objsubid = 0) " + "WHERE l.lanispl " + "ORDER BY l.oid", + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + username_subquery); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else if (fout->remoteVersion >= 90000) + { + /* pg_language has a laninline column */ + appendPQExpBuffer(query, "SELECT tableoid, oid, " + "lanname, lanpltrusted, lanplcallfoid, " + "laninline, lanvalidator, lanacl, NULL AS rlanacl, " + "NULL AS initlanacl, NULL AS initrlanacl, " + "(%s lanowner) AS lanowner " + "FROM pg_language " + "WHERE lanispl " + "ORDER BY oid", + username_subquery); + } + else if (fout->remoteVersion >= 80300) + { + /* pg_language has a lanowner column */ + appendPQExpBuffer(query, "SELECT tableoid, oid, " + "lanname, lanpltrusted, lanplcallfoid, " + "0 AS laninline, lanvalidator, lanacl, " + "NULL AS rlanacl, " + "NULL AS initlanacl, NULL AS initrlanacl, " + "(%s lanowner) AS lanowner " + "FROM pg_language " + "WHERE lanispl " + "ORDER BY oid", + username_subquery); + } + else if (fout->remoteVersion >= 80100) + { + /* Languages are owned by the bootstrap superuser, OID 10 */ + appendPQExpBuffer(query, "SELECT tableoid, oid, " + "lanname, lanpltrusted, lanplcallfoid, " + "0 AS laninline, lanvalidator, lanacl, " + "NULL AS rlanacl, " + "NULL AS initlanacl, NULL AS initrlanacl, " + "(%s '10') AS lanowner " + "FROM pg_language " + "WHERE lanispl " + "ORDER BY oid", + username_subquery); + } + else + { + /* Languages are owned by the bootstrap superuser, sysid 1 */ + appendPQExpBuffer(query, "SELECT tableoid, oid, " + "lanname, lanpltrusted, lanplcallfoid, " + "0 AS laninline, lanvalidator, lanacl, " + "NULL AS rlanacl, " + "NULL AS initlanacl, NULL AS initrlanacl, " + "(%s '1') AS lanowner " + "FROM pg_language " + "WHERE lanispl " + "ORDER BY oid", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numProcLangs = ntups; + + planginfo = (ProcLangInfo *) pg_malloc(ntups * sizeof(ProcLangInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_lanname = PQfnumber(res, "lanname"); + i_lanpltrusted = PQfnumber(res, "lanpltrusted"); + i_lanplcallfoid = PQfnumber(res, "lanplcallfoid"); + i_laninline = PQfnumber(res, "laninline"); + i_lanvalidator = PQfnumber(res, "lanvalidator"); + i_lanacl = PQfnumber(res, "lanacl"); + i_rlanacl = PQfnumber(res, "rlanacl"); + i_initlanacl = PQfnumber(res, "initlanacl"); + i_initrlanacl = PQfnumber(res, "initrlanacl"); + i_lanowner = PQfnumber(res, "lanowner"); + + for (i = 0; i < ntups; i++) + { + planginfo[i].dobj.objType = DO_PROCLANG; + planginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&planginfo[i].dobj); + + planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_lanname)); + planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't'; + planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid)); + planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline)); + planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator)); + planginfo[i].lanacl = pg_strdup(PQgetvalue(res, i, i_lanacl)); + planginfo[i].rlanacl = pg_strdup(PQgetvalue(res, i, i_rlanacl)); + planginfo[i].initlanacl = pg_strdup(PQgetvalue(res, i, i_initlanacl)); + planginfo[i].initrlanacl = pg_strdup(PQgetvalue(res, i, i_initrlanacl)); + planginfo[i].lanowner = pg_strdup(PQgetvalue(res, i, i_lanowner)); + + /* Decide whether we want to dump it */ + selectDumpableProcLang(&(planginfo[i]), fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_lanacl) && PQgetisnull(res, i, i_rlanacl) && + PQgetisnull(res, i, i_initlanacl) && + PQgetisnull(res, i, i_initrlanacl)) + planginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return planginfo; +} + +/* + * getCasts + * get basic information about most casts in the system + * + * numCasts is set to the number of casts read in + * + * Skip casts from a range to its multirange, since we'll create those + * automatically. + */ +CastInfo * +getCasts(Archive *fout, int *numCasts) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query = createPQExpBuffer(); + CastInfo *castinfo; + int i_tableoid; + int i_oid; + int i_castsource; + int i_casttarget; + int i_castfunc; + int i_castcontext; + int i_castmethod; + + if (fout->remoteVersion >= 140000) + { + appendPQExpBufferStr(query, "SELECT tableoid, oid, " + "castsource, casttarget, castfunc, castcontext, " + "castmethod " + "FROM pg_cast c " + "WHERE NOT EXISTS ( " + "SELECT 1 FROM pg_range r " + "WHERE c.castsource = r.rngtypid " + "AND c.casttarget = r.rngmultitypid " + ") " + "ORDER BY 3,4"); + } + else if (fout->remoteVersion >= 80400) + { + appendPQExpBufferStr(query, "SELECT tableoid, oid, " + "castsource, casttarget, castfunc, castcontext, " + "castmethod " + "FROM pg_cast ORDER BY 3,4"); + } + else + { + appendPQExpBufferStr(query, "SELECT tableoid, oid, " + "castsource, casttarget, castfunc, castcontext, " + "CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod " + "FROM pg_cast ORDER BY 3,4"); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numCasts = ntups; + + castinfo = (CastInfo *) pg_malloc(ntups * sizeof(CastInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_castsource = PQfnumber(res, "castsource"); + i_casttarget = PQfnumber(res, "casttarget"); + i_castfunc = PQfnumber(res, "castfunc"); + i_castcontext = PQfnumber(res, "castcontext"); + i_castmethod = PQfnumber(res, "castmethod"); + + for (i = 0; i < ntups; i++) + { + PQExpBufferData namebuf; + TypeInfo *sTypeInfo; + TypeInfo *tTypeInfo; + + castinfo[i].dobj.objType = DO_CAST; + castinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + castinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&castinfo[i].dobj); + castinfo[i].castsource = atooid(PQgetvalue(res, i, i_castsource)); + castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget)); + castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc)); + castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext)); + castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod)); + + /* + * Try to name cast as concatenation of typnames. This is only used + * for purposes of sorting. If we fail to find either type, the name + * will be an empty string. + */ + initPQExpBuffer(&namebuf); + sTypeInfo = findTypeByOid(castinfo[i].castsource); + tTypeInfo = findTypeByOid(castinfo[i].casttarget); + if (sTypeInfo && tTypeInfo) + appendPQExpBuffer(&namebuf, "%s %s", + sTypeInfo->dobj.name, tTypeInfo->dobj.name); + castinfo[i].dobj.name = namebuf.data; + + /* Decide whether we want to dump it */ + selectDumpableCast(&(castinfo[i]), fout); + + /* Casts do not currently have ACLs. */ + castinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return castinfo; +} + +static char * +get_language_name(Archive *fout, Oid langid) +{ + PQExpBuffer query; + PGresult *res; + char *lanname; + + query = createPQExpBuffer(); + appendPQExpBuffer(query, "SELECT lanname FROM pg_language WHERE oid = %u", langid); + res = ExecuteSqlQueryForSingleRow(fout, query->data); + lanname = pg_strdup(fmtId(PQgetvalue(res, 0, 0))); + destroyPQExpBuffer(query); + PQclear(res); + + return lanname; +} + +/* + * getTransforms + * get basic information about every transform in the system + * + * numTransforms is set to the number of transforms read in + */ +TransformInfo * +getTransforms(Archive *fout, int *numTransforms) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + TransformInfo *transforminfo; + int i_tableoid; + int i_oid; + int i_trftype; + int i_trflang; + int i_trffromsql; + int i_trftosql; + + /* Transforms didn't exist pre-9.5 */ + if (fout->remoteVersion < 90500) + { + *numTransforms = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SELECT tableoid, oid, " + "trftype, trflang, trffromsql::oid, trftosql::oid " + "FROM pg_transform " + "ORDER BY 3,4"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + *numTransforms = ntups; + + transforminfo = (TransformInfo *) pg_malloc(ntups * sizeof(TransformInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_trftype = PQfnumber(res, "trftype"); + i_trflang = PQfnumber(res, "trflang"); + i_trffromsql = PQfnumber(res, "trffromsql"); + i_trftosql = PQfnumber(res, "trftosql"); + + for (i = 0; i < ntups; i++) + { + PQExpBufferData namebuf; + TypeInfo *typeInfo; + char *lanname; + + transforminfo[i].dobj.objType = DO_TRANSFORM; + transforminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + transforminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&transforminfo[i].dobj); + transforminfo[i].trftype = atooid(PQgetvalue(res, i, i_trftype)); + transforminfo[i].trflang = atooid(PQgetvalue(res, i, i_trflang)); + transforminfo[i].trffromsql = atooid(PQgetvalue(res, i, i_trffromsql)); + transforminfo[i].trftosql = atooid(PQgetvalue(res, i, i_trftosql)); + + /* + * Try to name transform as concatenation of type and language name. + * This is only used for purposes of sorting. If we fail to find + * either, the name will be an empty string. + */ + initPQExpBuffer(&namebuf); + typeInfo = findTypeByOid(transforminfo[i].trftype); + lanname = get_language_name(fout, transforminfo[i].trflang); + if (typeInfo && lanname) + appendPQExpBuffer(&namebuf, "%s %s", + typeInfo->dobj.name, lanname); + transforminfo[i].dobj.name = namebuf.data; + free(lanname); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(transforminfo[i].dobj), fout); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return transforminfo; +} + +/* + * getTableAttrs - + * for each interesting table, read info about its attributes + * (names, types, default values, CHECK constraints, etc) + * + * This is implemented in a very inefficient way right now, looping + * through the tblinfo and doing a join per table to find the attrs and their + * types. However, because we want type names and so forth to be named + * relative to the schema of each table, we couldn't do it in just one + * query. (Maybe one query per schema?) + * + * modifies tblinfo + */ +void +getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + + for (int i = 0; i < numTables; i++) + { + TableInfo *tbinfo = &tblinfo[i]; + PGresult *res; + int ntups; + bool hasdefaults; + + /* Don't bother to collect info for sequences */ + if (tbinfo->relkind == RELKIND_SEQUENCE) + continue; + + /* Don't bother with uninteresting tables, either */ + if (!tbinfo->interesting) + continue; + + /* find all the user attributes and their types */ + + /* + * we must read the attribute names in attribute number order! because + * we will use the attnum to index into the attnames array later. + */ + pg_log_info("finding the columns and types of table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + resetPQExpBuffer(q); + + appendPQExpBufferStr(q, + "SELECT\n" + "a.attnum,\n" + "a.attname,\n" + "a.atttypmod,\n" + "a.attstattarget,\n" + "a.attstorage,\n" + "t.typstorage,\n" + "a.attnotnull,\n" + "a.atthasdef,\n" + "a.attisdropped,\n" + "a.attlen,\n" + "a.attalign,\n" + "a.attislocal,\n" + "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n"); + + if (fout->remoteVersion >= 90000) + appendPQExpBufferStr(q, + "array_to_string(a.attoptions, ', ') AS attoptions,\n"); + else + appendPQExpBufferStr(q, + "'' AS attoptions,\n"); + + if (fout->remoteVersion >= 90100) + { + /* + * Since we only want to dump COLLATE clauses for attributes whose + * collation is different from their type's default, we use a CASE + * here to suppress uninteresting attcollations cheaply. + */ + appendPQExpBufferStr(q, + "CASE WHEN a.attcollation <> t.typcollation " + "THEN a.attcollation ELSE 0 END AS attcollation,\n"); + } + else + appendPQExpBufferStr(q, + "0 AS attcollation,\n"); + + if (fout->remoteVersion >= 140000) + appendPQExpBuffer(q, + "a.attcompression AS attcompression,\n"); + else + appendPQExpBuffer(q, + "'' AS attcompression,\n"); + + if (fout->remoteVersion >= 90200) + appendPQExpBufferStr(q, + "pg_catalog.array_to_string(ARRAY(" + "SELECT pg_catalog.quote_ident(option_name) || " + "' ' || pg_catalog.quote_literal(option_value) " + "FROM pg_catalog.pg_options_to_table(attfdwoptions) " + "ORDER BY option_name" + "), E',\n ') AS attfdwoptions,\n"); + else + appendPQExpBufferStr(q, + "'' AS attfdwoptions,\n"); + + if (fout->remoteVersion >= 100000) + appendPQExpBufferStr(q, + "a.attidentity,\n"); + else + appendPQExpBufferStr(q, + "'' AS attidentity,\n"); + + if (fout->remoteVersion >= 110000) + appendPQExpBufferStr(q, + "CASE WHEN a.atthasmissing AND NOT a.attisdropped " + "THEN a.attmissingval ELSE null END AS attmissingval,\n"); + else + appendPQExpBufferStr(q, + "NULL AS attmissingval,\n"); + + if (fout->remoteVersion >= 120000) + appendPQExpBufferStr(q, + "a.attgenerated\n"); + else + appendPQExpBufferStr(q, + "'' AS attgenerated\n"); + + /* need left join here to not fail on dropped columns ... */ + appendPQExpBuffer(q, + "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t " + "ON a.atttypid = t.oid\n" + "WHERE a.attrelid = '%u'::pg_catalog.oid " + "AND a.attnum > 0::pg_catalog.int2\n" + "ORDER BY a.attnum", + tbinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + tbinfo->numatts = ntups; + tbinfo->attnames = (char **) pg_malloc(ntups * sizeof(char *)); + tbinfo->atttypnames = (char **) pg_malloc(ntups * sizeof(char *)); + tbinfo->atttypmod = (int *) pg_malloc(ntups * sizeof(int)); + tbinfo->attstattarget = (int *) pg_malloc(ntups * sizeof(int)); + tbinfo->attstorage = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->typstorage = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->attidentity = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->attgenerated = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->attisdropped = (bool *) pg_malloc(ntups * sizeof(bool)); + tbinfo->attlen = (int *) pg_malloc(ntups * sizeof(int)); + tbinfo->attalign = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->attislocal = (bool *) pg_malloc(ntups * sizeof(bool)); + tbinfo->attoptions = (char **) pg_malloc(ntups * sizeof(char *)); + tbinfo->attcollation = (Oid *) pg_malloc(ntups * sizeof(Oid)); + tbinfo->attcompression = (char *) pg_malloc(ntups * sizeof(char)); + tbinfo->attfdwoptions = (char **) pg_malloc(ntups * sizeof(char *)); + tbinfo->attmissingval = (char **) pg_malloc(ntups * sizeof(char *)); + tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool)); + tbinfo->inhNotNull = (bool *) pg_malloc(ntups * sizeof(bool)); + tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *)); + hasdefaults = false; + + for (int j = 0; j < ntups; j++) + { + if (j + 1 != atoi(PQgetvalue(res, j, PQfnumber(res, "attnum")))) + fatal("invalid column numbering in table \"%s\"", + tbinfo->dobj.name); + tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attname"))); + tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "atttypname"))); + tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "atttypmod"))); + tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "attstattarget"))); + tbinfo->attstorage[j] = *(PQgetvalue(res, j, PQfnumber(res, "attstorage"))); + tbinfo->typstorage[j] = *(PQgetvalue(res, j, PQfnumber(res, "typstorage"))); + tbinfo->attidentity[j] = *(PQgetvalue(res, j, PQfnumber(res, "attidentity"))); + tbinfo->attgenerated[j] = *(PQgetvalue(res, j, PQfnumber(res, "attgenerated"))); + tbinfo->needs_override = tbinfo->needs_override || (tbinfo->attidentity[j] == ATTRIBUTE_IDENTITY_ALWAYS); + tbinfo->attisdropped[j] = (PQgetvalue(res, j, PQfnumber(res, "attisdropped"))[0] == 't'); + tbinfo->attlen[j] = atoi(PQgetvalue(res, j, PQfnumber(res, "attlen"))); + tbinfo->attalign[j] = *(PQgetvalue(res, j, PQfnumber(res, "attalign"))); + tbinfo->attislocal[j] = (PQgetvalue(res, j, PQfnumber(res, "attislocal"))[0] == 't'); + tbinfo->notnull[j] = (PQgetvalue(res, j, PQfnumber(res, "attnotnull"))[0] == 't'); + tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attoptions"))); + tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, PQfnumber(res, "attcollation"))); + tbinfo->attcompression[j] = *(PQgetvalue(res, j, PQfnumber(res, "attcompression"))); + tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attfdwoptions"))); + tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, j, PQfnumber(res, "attmissingval"))); + tbinfo->attrdefs[j] = NULL; /* fix below */ + if (PQgetvalue(res, j, PQfnumber(res, "atthasdef"))[0] == 't') + hasdefaults = true; + /* these flags will be set in flagInhAttrs() */ + tbinfo->inhNotNull[j] = false; + } + + PQclear(res); + + /* + * Get info about column defaults. This is skipped for a data-only + * dump, as it is only needed for table schemas. + */ + if (!dopt->dataOnly && hasdefaults) + { + AttrDefInfo *attrdefs; + int numDefaults; + + pg_log_info("finding default expressions of table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + printfPQExpBuffer(q, "SELECT tableoid, oid, adnum, " + "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc " + "FROM pg_catalog.pg_attrdef " + "WHERE adrelid = '%u'::pg_catalog.oid", + tbinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); + + numDefaults = PQntuples(res); + attrdefs = (AttrDefInfo *) pg_malloc(numDefaults * sizeof(AttrDefInfo)); + + for (int j = 0; j < numDefaults; j++) + { + int adnum; + + adnum = atoi(PQgetvalue(res, j, 2)); + + if (adnum <= 0 || adnum > ntups) + fatal("invalid adnum value %d for table \"%s\"", + adnum, tbinfo->dobj.name); + + /* + * dropped columns shouldn't have defaults, but just in case, + * ignore 'em + */ + if (tbinfo->attisdropped[adnum - 1]) + continue; + + attrdefs[j].dobj.objType = DO_ATTRDEF; + attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0)); + attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1)); + AssignDumpId(&attrdefs[j].dobj); + attrdefs[j].adtable = tbinfo; + attrdefs[j].adnum = adnum; + attrdefs[j].adef_expr = pg_strdup(PQgetvalue(res, j, 3)); + + attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name); + attrdefs[j].dobj.namespace = tbinfo->dobj.namespace; + + attrdefs[j].dobj.dump = tbinfo->dobj.dump; + + /* + * Figure out whether the default/generation expression should + * be dumped as part of the main CREATE TABLE (or similar) + * command or as a separate ALTER TABLE (or similar) command. + * The preference is to put it into the CREATE command, but in + * some cases that's not possible. + */ + if (tbinfo->attgenerated[adnum - 1]) + { + /* + * Column generation expressions cannot be dumped + * separately, because there is no syntax for it. The + * !shouldPrintColumn case below will be tempted to set + * them to separate if they are attached to an inherited + * column without a local definition, but that would be + * wrong and unnecessary, because generation expressions + * are always inherited, so there is no need to set them + * again in child tables, and there is no syntax for it + * either. By setting separate to false here we prevent + * the "default" from being processed as its own dumpable + * object, and flagInhAttrs() will remove it from the + * table when it detects that it belongs to an inherited + * column. + */ + attrdefs[j].separate = false; + } + else if (tbinfo->relkind == RELKIND_VIEW) + { + /* + * Defaults on a VIEW must always be dumped as separate + * ALTER TABLE commands. + */ + attrdefs[j].separate = true; + } + else if (!shouldPrintColumn(dopt, tbinfo, adnum - 1)) + { + /* column will be suppressed, print default separately */ + attrdefs[j].separate = true; + } + else + { + attrdefs[j].separate = false; + } + + if (!attrdefs[j].separate) + { + /* + * Mark the default as needing to appear before the table, + * so that any dependencies it has must be emitted before + * the CREATE TABLE. If this is not possible, we'll + * change to "separate" mode while sorting dependencies. + */ + addObjectDependency(&tbinfo->dobj, + attrdefs[j].dobj.dumpId); + } + + tbinfo->attrdefs[adnum - 1] = &attrdefs[j]; + } + PQclear(res); + } + + /* + * Get info about table CHECK constraints. This is skipped for a + * data-only dump, as it is only needed for table schemas. + */ + if (tbinfo->ncheck > 0 && !dopt->dataOnly) + { + ConstraintInfo *constrs; + int numConstrs; + + pg_log_info("finding check constraints for table \"%s.%s\"", + tbinfo->dobj.namespace->dobj.name, + tbinfo->dobj.name); + + resetPQExpBuffer(q); + if (fout->remoteVersion >= 90200) + { + /* + * convalidated is new in 9.2 (actually, it is there in 9.1, + * but it wasn't ever false for check constraints until 9.2). + */ + appendPQExpBuffer(q, "SELECT tableoid, oid, conname, " + "pg_catalog.pg_get_constraintdef(oid) AS consrc, " + "conislocal, convalidated " + "FROM pg_catalog.pg_constraint " + "WHERE conrelid = '%u'::pg_catalog.oid " + " AND contype = 'c' " + "ORDER BY conname", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80400) + { + /* conislocal is new in 8.4 */ + appendPQExpBuffer(q, "SELECT tableoid, oid, conname, " + "pg_catalog.pg_get_constraintdef(oid) AS consrc, " + "conislocal, true AS convalidated " + "FROM pg_catalog.pg_constraint " + "WHERE conrelid = '%u'::pg_catalog.oid " + " AND contype = 'c' " + "ORDER BY conname", + tbinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(q, "SELECT tableoid, oid, conname, " + "pg_catalog.pg_get_constraintdef(oid) AS consrc, " + "true AS conislocal, true AS convalidated " + "FROM pg_catalog.pg_constraint " + "WHERE conrelid = '%u'::pg_catalog.oid " + " AND contype = 'c' " + "ORDER BY conname", + tbinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); + + numConstrs = PQntuples(res); + if (numConstrs != tbinfo->ncheck) + { + pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d", + "expected %d check constraints on table \"%s\" but found %d", + tbinfo->ncheck), + tbinfo->ncheck, tbinfo->dobj.name, numConstrs); + pg_log_error("(The system catalogs might be corrupted.)"); + exit_nicely(1); + } + + constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo)); + tbinfo->checkexprs = constrs; + + for (int j = 0; j < numConstrs; j++) + { + bool validated = PQgetvalue(res, j, 5)[0] == 't'; + + constrs[j].dobj.objType = DO_CONSTRAINT; + constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0)); + constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1)); + AssignDumpId(&constrs[j].dobj); + constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, 2)); + constrs[j].dobj.namespace = tbinfo->dobj.namespace; + constrs[j].contable = tbinfo; + constrs[j].condomain = NULL; + constrs[j].contype = 'c'; + constrs[j].condef = pg_strdup(PQgetvalue(res, j, 3)); + constrs[j].confrelid = InvalidOid; + constrs[j].conindex = 0; + constrs[j].condeferrable = false; + constrs[j].condeferred = false; + constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't'); + + /* + * An unvalidated constraint needs to be dumped separately, so + * that potentially-violating existing data is loaded before + * the constraint. + */ + constrs[j].separate = !validated; + + constrs[j].dobj.dump = tbinfo->dobj.dump; + + /* + * Mark the constraint as needing to appear before the table + * --- this is so that any other dependencies of the + * constraint will be emitted before we try to create the + * table. If the constraint is to be dumped separately, it + * will be dumped after data is loaded anyway, so don't do it. + * (There's an automatic dependency in the opposite direction + * anyway, so don't need to add one manually here.) + */ + if (!constrs[j].separate) + addObjectDependency(&tbinfo->dobj, + constrs[j].dobj.dumpId); + + /* + * If the constraint is inherited, this will be detected later + * (in pre-8.4 databases). We also detect later if the + * constraint must be split out from the table definition. + */ + } + PQclear(res); + } + } + + destroyPQExpBuffer(q); +} + +/* + * Test whether a column should be printed as part of table's CREATE TABLE. + * Column number is zero-based. + * + * Normally this is always true, but it's false for dropped columns, as well + * as those that were inherited without any local definition. (If we print + * such a column it will mistakenly get pg_attribute.attislocal set to true.) + * For partitions, it's always true, because we want the partitions to be + * created independently and ATTACH PARTITION used afterwards. + * + * In binary_upgrade mode, we must print all columns and fix the attislocal/ + * attisdropped state later, so as to keep control of the physical column + * order. + * + * This function exists because there are scattered nonobvious places that + * must be kept in sync with this decision. + */ +bool +shouldPrintColumn(const DumpOptions *dopt, const TableInfo *tbinfo, int colno) +{ + if (dopt->binary_upgrade) + return true; + if (tbinfo->attisdropped[colno]) + return false; + return (tbinfo->attislocal[colno] || tbinfo->ispartition); +} + + +/* + * getTSParsers: + * read all text search parsers in the system catalogs and return them + * in the TSParserInfo* structure + * + * numTSParsers is set to the number of parsers read in + */ +TSParserInfo * +getTSParsers(Archive *fout, int *numTSParsers) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + TSParserInfo *prsinfo; + int i_tableoid; + int i_oid; + int i_prsname; + int i_prsnamespace; + int i_prsstart; + int i_prstoken; + int i_prsend; + int i_prsheadline; + int i_prslextype; + + /* Before 8.3, there is no built-in text search support */ + if (fout->remoteVersion < 80300) + { + *numTSParsers = 0; + return NULL; + } + + query = createPQExpBuffer(); + + /* + * find all text search objects, including builtin ones; we filter out + * system-defined objects at dump-out time. + */ + + appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, " + "prsstart::oid, prstoken::oid, " + "prsend::oid, prsheadline::oid, prslextype::oid " + "FROM pg_ts_parser"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numTSParsers = ntups; + + prsinfo = (TSParserInfo *) pg_malloc(ntups * sizeof(TSParserInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_prsname = PQfnumber(res, "prsname"); + i_prsnamespace = PQfnumber(res, "prsnamespace"); + i_prsstart = PQfnumber(res, "prsstart"); + i_prstoken = PQfnumber(res, "prstoken"); + i_prsend = PQfnumber(res, "prsend"); + i_prsheadline = PQfnumber(res, "prsheadline"); + i_prslextype = PQfnumber(res, "prslextype"); + + for (i = 0; i < ntups; i++) + { + prsinfo[i].dobj.objType = DO_TSPARSER; + prsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&prsinfo[i].dobj); + prsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_prsname)); + prsinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace))); + prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart)); + prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken)); + prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend)); + prsinfo[i].prsheadline = atooid(PQgetvalue(res, i, i_prsheadline)); + prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(prsinfo[i].dobj), fout); + + /* Text Search Parsers do not currently have ACLs. */ + prsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return prsinfo; +} + +/* + * getTSDictionaries: + * read all text search dictionaries in the system catalogs and return them + * in the TSDictInfo* structure + * + * numTSDicts is set to the number of dictionaries read in + */ +TSDictInfo * +getTSDictionaries(Archive *fout, int *numTSDicts) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + TSDictInfo *dictinfo; + int i_tableoid; + int i_oid; + int i_dictname; + int i_dictnamespace; + int i_rolname; + int i_dicttemplate; + int i_dictinitoption; + + /* Before 8.3, there is no built-in text search support */ + if (fout->remoteVersion < 80300) + { + *numTSDicts = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, " + "dictnamespace, (%s dictowner) AS rolname, " + "dicttemplate, dictinitoption " + "FROM pg_ts_dict", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numTSDicts = ntups; + + dictinfo = (TSDictInfo *) pg_malloc(ntups * sizeof(TSDictInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_dictname = PQfnumber(res, "dictname"); + i_dictnamespace = PQfnumber(res, "dictnamespace"); + i_rolname = PQfnumber(res, "rolname"); + i_dictinitoption = PQfnumber(res, "dictinitoption"); + i_dicttemplate = PQfnumber(res, "dicttemplate"); + + for (i = 0; i < ntups; i++) + { + dictinfo[i].dobj.objType = DO_TSDICT; + dictinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&dictinfo[i].dobj); + dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname)); + dictinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace))); + dictinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate)); + if (PQgetisnull(res, i, i_dictinitoption)) + dictinfo[i].dictinitoption = NULL; + else + dictinfo[i].dictinitoption = pg_strdup(PQgetvalue(res, i, i_dictinitoption)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(dictinfo[i].dobj), fout); + + /* Text Search Dictionaries do not currently have ACLs. */ + dictinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return dictinfo; +} + +/* + * getTSTemplates: + * read all text search templates in the system catalogs and return them + * in the TSTemplateInfo* structure + * + * numTSTemplates is set to the number of templates read in + */ +TSTemplateInfo * +getTSTemplates(Archive *fout, int *numTSTemplates) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + TSTemplateInfo *tmplinfo; + int i_tableoid; + int i_oid; + int i_tmplname; + int i_tmplnamespace; + int i_tmplinit; + int i_tmpllexize; + + /* Before 8.3, there is no built-in text search support */ + if (fout->remoteVersion < 80300) + { + *numTSTemplates = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, " + "tmplnamespace, tmplinit::oid, tmpllexize::oid " + "FROM pg_ts_template"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numTSTemplates = ntups; + + tmplinfo = (TSTemplateInfo *) pg_malloc(ntups * sizeof(TSTemplateInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_tmplname = PQfnumber(res, "tmplname"); + i_tmplnamespace = PQfnumber(res, "tmplnamespace"); + i_tmplinit = PQfnumber(res, "tmplinit"); + i_tmpllexize = PQfnumber(res, "tmpllexize"); + + for (i = 0; i < ntups; i++) + { + tmplinfo[i].dobj.objType = DO_TSTEMPLATE; + tmplinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&tmplinfo[i].dobj); + tmplinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_tmplname)); + tmplinfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace))); + tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit)); + tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(tmplinfo[i].dobj), fout); + + /* Text Search Templates do not currently have ACLs. */ + tmplinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return tmplinfo; +} + +/* + * getTSConfigurations: + * read all text search configurations in the system catalogs and return + * them in the TSConfigInfo* structure + * + * numTSConfigs is set to the number of configurations read in + */ +TSConfigInfo * +getTSConfigurations(Archive *fout, int *numTSConfigs) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + TSConfigInfo *cfginfo; + int i_tableoid; + int i_oid; + int i_cfgname; + int i_cfgnamespace; + int i_rolname; + int i_cfgparser; + + /* Before 8.3, there is no built-in text search support */ + if (fout->remoteVersion < 80300) + { + *numTSConfigs = 0; + return NULL; + } + + query = createPQExpBuffer(); + + appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, " + "cfgnamespace, (%s cfgowner) AS rolname, cfgparser " + "FROM pg_ts_config", + username_subquery); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numTSConfigs = ntups; + + cfginfo = (TSConfigInfo *) pg_malloc(ntups * sizeof(TSConfigInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_cfgname = PQfnumber(res, "cfgname"); + i_cfgnamespace = PQfnumber(res, "cfgnamespace"); + i_rolname = PQfnumber(res, "rolname"); + i_cfgparser = PQfnumber(res, "cfgparser"); + + for (i = 0; i < ntups; i++) + { + cfginfo[i].dobj.objType = DO_TSCONFIG; + cfginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&cfginfo[i].dobj); + cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname)); + cfginfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace))); + cfginfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(cfginfo[i].dobj), fout); + + /* Text Search Configurations do not currently have ACLs. */ + cfginfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return cfginfo; +} + +/* + * getForeignDataWrappers: + * read all foreign-data wrappers in the system catalogs and return + * them in the FdwInfo* structure + * + * numForeignDataWrappers is set to the number of fdws read in + */ +FdwInfo * +getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + FdwInfo *fdwinfo; + int i_tableoid; + int i_oid; + int i_fdwname; + int i_rolname; + int i_fdwhandler; + int i_fdwvalidator; + int i_fdwacl; + int i_rfdwacl; + int i_initfdwacl; + int i_initrfdwacl; + int i_fdwoptions; + + /* Before 8.4, there are no foreign-data wrappers */ + if (fout->remoteVersion < 80400) + { + *numForeignDataWrappers = 0; + return NULL; + } + + query = createPQExpBuffer(); + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "f.fdwacl", "f.fdwowner", "'F'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.fdwname, " + "(%s f.fdwowner) AS rolname, " + "f.fdwhandler::pg_catalog.regproc, " + "f.fdwvalidator::pg_catalog.regproc, " + "%s AS fdwacl, " + "%s AS rfdwacl, " + "%s AS initfdwacl, " + "%s AS initrfdwacl, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(f.fdwoptions) " + "ORDER BY option_name" + "), E',\n ') AS fdwoptions " + "FROM pg_foreign_data_wrapper f " + "LEFT JOIN pg_init_privs pip ON " + "(f.oid = pip.objoid " + "AND pip.classoid = 'pg_foreign_data_wrapper'::regclass " + "AND pip.objsubid = 0) ", + username_subquery, + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else if (fout->remoteVersion >= 90100) + { + appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, " + "(%s fdwowner) AS rolname, " + "fdwhandler::pg_catalog.regproc, " + "fdwvalidator::pg_catalog.regproc, fdwacl, " + "NULL as rfdwacl, " + "NULL as initfdwacl, NULL AS initrfdwacl, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(fdwoptions) " + "ORDER BY option_name" + "), E',\n ') AS fdwoptions " + "FROM pg_foreign_data_wrapper", + username_subquery); + } + else + { + appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, " + "(%s fdwowner) AS rolname, " + "'-' AS fdwhandler, " + "fdwvalidator::pg_catalog.regproc, fdwacl, " + "NULL as rfdwacl, " + "NULL as initfdwacl, NULL AS initrfdwacl, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(fdwoptions) " + "ORDER BY option_name" + "), E',\n ') AS fdwoptions " + "FROM pg_foreign_data_wrapper", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numForeignDataWrappers = ntups; + + fdwinfo = (FdwInfo *) pg_malloc(ntups * sizeof(FdwInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_fdwname = PQfnumber(res, "fdwname"); + i_rolname = PQfnumber(res, "rolname"); + i_fdwhandler = PQfnumber(res, "fdwhandler"); + i_fdwvalidator = PQfnumber(res, "fdwvalidator"); + i_fdwacl = PQfnumber(res, "fdwacl"); + i_rfdwacl = PQfnumber(res, "rfdwacl"); + i_initfdwacl = PQfnumber(res, "initfdwacl"); + i_initrfdwacl = PQfnumber(res, "initrfdwacl"); + i_fdwoptions = PQfnumber(res, "fdwoptions"); + + for (i = 0; i < ntups; i++) + { + fdwinfo[i].dobj.objType = DO_FDW; + fdwinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&fdwinfo[i].dobj); + fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname)); + fdwinfo[i].dobj.namespace = NULL; + fdwinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, i_fdwhandler)); + fdwinfo[i].fdwvalidator = pg_strdup(PQgetvalue(res, i, i_fdwvalidator)); + fdwinfo[i].fdwoptions = pg_strdup(PQgetvalue(res, i, i_fdwoptions)); + fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl)); + fdwinfo[i].rfdwacl = pg_strdup(PQgetvalue(res, i, i_rfdwacl)); + fdwinfo[i].initfdwacl = pg_strdup(PQgetvalue(res, i, i_initfdwacl)); + fdwinfo[i].initrfdwacl = pg_strdup(PQgetvalue(res, i, i_initrfdwacl)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(fdwinfo[i].dobj), fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_fdwacl) && PQgetisnull(res, i, i_rfdwacl) && + PQgetisnull(res, i, i_initfdwacl) && + PQgetisnull(res, i, i_initrfdwacl)) + fdwinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return fdwinfo; +} + +/* + * getForeignServers: + * read all foreign servers in the system catalogs and return + * them in the ForeignServerInfo * structure + * + * numForeignServers is set to the number of servers read in + */ +ForeignServerInfo * +getForeignServers(Archive *fout, int *numForeignServers) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + ForeignServerInfo *srvinfo; + int i_tableoid; + int i_oid; + int i_srvname; + int i_rolname; + int i_srvfdw; + int i_srvtype; + int i_srvversion; + int i_srvacl; + int i_rsrvacl; + int i_initsrvacl; + int i_initrsrvacl; + int i_srvoptions; + + /* Before 8.4, there are no foreign servers */ + if (fout->remoteVersion < 80400) + { + *numForeignServers = 0; + return NULL; + } + + query = createPQExpBuffer(); + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "f.srvacl", "f.srvowner", "'S'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, "SELECT f.tableoid, f.oid, f.srvname, " + "(%s f.srvowner) AS rolname, " + "f.srvfdw, f.srvtype, f.srvversion, " + "%s AS srvacl, " + "%s AS rsrvacl, " + "%s AS initsrvacl, " + "%s AS initrsrvacl, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(f.srvoptions) " + "ORDER BY option_name" + "), E',\n ') AS srvoptions " + "FROM pg_foreign_server f " + "LEFT JOIN pg_init_privs pip " + "ON (f.oid = pip.objoid " + "AND pip.classoid = 'pg_foreign_server'::regclass " + "AND pip.objsubid = 0) ", + username_subquery, + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else + { + appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, " + "(%s srvowner) AS rolname, " + "srvfdw, srvtype, srvversion, srvacl, " + "NULL AS rsrvacl, " + "NULL AS initsrvacl, NULL AS initrsrvacl, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(srvoptions) " + "ORDER BY option_name" + "), E',\n ') AS srvoptions " + "FROM pg_foreign_server", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numForeignServers = ntups; + + srvinfo = (ForeignServerInfo *) pg_malloc(ntups * sizeof(ForeignServerInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_srvname = PQfnumber(res, "srvname"); + i_rolname = PQfnumber(res, "rolname"); + i_srvfdw = PQfnumber(res, "srvfdw"); + i_srvtype = PQfnumber(res, "srvtype"); + i_srvversion = PQfnumber(res, "srvversion"); + i_srvacl = PQfnumber(res, "srvacl"); + i_rsrvacl = PQfnumber(res, "rsrvacl"); + i_initsrvacl = PQfnumber(res, "initsrvacl"); + i_initrsrvacl = PQfnumber(res, "initrsrvacl"); + i_srvoptions = PQfnumber(res, "srvoptions"); + + for (i = 0; i < ntups; i++) + { + srvinfo[i].dobj.objType = DO_FOREIGN_SERVER; + srvinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&srvinfo[i].dobj); + srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname)); + srvinfo[i].dobj.namespace = NULL; + srvinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname)); + srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw)); + srvinfo[i].srvtype = pg_strdup(PQgetvalue(res, i, i_srvtype)); + srvinfo[i].srvversion = pg_strdup(PQgetvalue(res, i, i_srvversion)); + srvinfo[i].srvoptions = pg_strdup(PQgetvalue(res, i, i_srvoptions)); + srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl)); + srvinfo[i].rsrvacl = pg_strdup(PQgetvalue(res, i, i_rsrvacl)); + srvinfo[i].initsrvacl = pg_strdup(PQgetvalue(res, i, i_initsrvacl)); + srvinfo[i].initrsrvacl = pg_strdup(PQgetvalue(res, i, i_initrsrvacl)); + + /* Decide whether we want to dump it */ + selectDumpableObject(&(srvinfo[i].dobj), fout); + + /* Do not try to dump ACL if no ACL exists. */ + if (PQgetisnull(res, i, i_srvacl) && PQgetisnull(res, i, i_rsrvacl) && + PQgetisnull(res, i, i_initsrvacl) && + PQgetisnull(res, i, i_initrsrvacl)) + srvinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL; + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return srvinfo; +} + +/* + * getDefaultACLs: + * read all default ACL information in the system catalogs and return + * them in the DefaultACLInfo structure + * + * numDefaultACLs is set to the number of ACLs read in + */ +DefaultACLInfo * +getDefaultACLs(Archive *fout, int *numDefaultACLs) +{ + DumpOptions *dopt = fout->dopt; + DefaultACLInfo *daclinfo; + PQExpBuffer query; + PGresult *res; + int i_oid; + int i_tableoid; + int i_defaclrole; + int i_defaclnamespace; + int i_defaclobjtype; + int i_defaclacl; + int i_rdefaclacl; + int i_initdefaclacl; + int i_initrdefaclacl; + int i, + ntups; + + if (fout->remoteVersion < 90000) + { + *numDefaultACLs = 0; + return NULL; + } + + query = createPQExpBuffer(); + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + /* + * Global entries (with defaclnamespace=0) replace the hard-wired + * default ACL for their object type. We should dump them as deltas + * from the default ACL, since that will be used as a starting point + * for interpreting the ALTER DEFAULT PRIVILEGES commands. On the + * other hand, non-global entries can only add privileges not revoke + * them. We must dump those as-is (i.e., as deltas from an empty + * ACL). We implement that by passing NULL as the object type for + * acldefault(), which works because acldefault() is STRICT. + * + * We can use defaclobjtype as the object type for acldefault(), + * except for the case of 'S' (DEFACLOBJ_SEQUENCE) which must be + * converted to 's'. + */ + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "defaclacl", "defaclrole", + "CASE WHEN defaclnamespace = 0 THEN" + " CASE WHEN defaclobjtype = 'S' THEN 's'::\"char\"" + " ELSE defaclobjtype END " + "ELSE NULL END", + dopt->binary_upgrade); + + appendPQExpBuffer(query, "SELECT d.oid, d.tableoid, " + "(%s d.defaclrole) AS defaclrole, " + "d.defaclnamespace, " + "d.defaclobjtype, " + "%s AS defaclacl, " + "%s AS rdefaclacl, " + "%s AS initdefaclacl, " + "%s AS initrdefaclacl " + "FROM pg_default_acl d " + "LEFT JOIN pg_init_privs pip ON " + "(d.oid = pip.objoid " + "AND pip.classoid = 'pg_default_acl'::regclass " + "AND pip.objsubid = 0) ", + username_subquery, + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else + { + appendPQExpBuffer(query, "SELECT oid, tableoid, " + "(%s defaclrole) AS defaclrole, " + "defaclnamespace, " + "defaclobjtype, " + "defaclacl, " + "NULL AS rdefaclacl, " + "NULL AS initdefaclacl, " + "NULL AS initrdefaclacl " + "FROM pg_default_acl", + username_subquery); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + *numDefaultACLs = ntups; + + daclinfo = (DefaultACLInfo *) pg_malloc(ntups * sizeof(DefaultACLInfo)); + + i_oid = PQfnumber(res, "oid"); + i_tableoid = PQfnumber(res, "tableoid"); + i_defaclrole = PQfnumber(res, "defaclrole"); + i_defaclnamespace = PQfnumber(res, "defaclnamespace"); + i_defaclobjtype = PQfnumber(res, "defaclobjtype"); + i_defaclacl = PQfnumber(res, "defaclacl"); + i_rdefaclacl = PQfnumber(res, "rdefaclacl"); + i_initdefaclacl = PQfnumber(res, "initdefaclacl"); + i_initrdefaclacl = PQfnumber(res, "initrdefaclacl"); + + for (i = 0; i < ntups; i++) + { + Oid nspid = atooid(PQgetvalue(res, i, i_defaclnamespace)); + + daclinfo[i].dobj.objType = DO_DEFAULT_ACL; + daclinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + daclinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&daclinfo[i].dobj); + /* cheesy ... is it worth coming up with a better object name? */ + daclinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_defaclobjtype)); + + if (nspid != InvalidOid) + daclinfo[i].dobj.namespace = findNamespace(nspid); + else + daclinfo[i].dobj.namespace = NULL; + + daclinfo[i].defaclrole = pg_strdup(PQgetvalue(res, i, i_defaclrole)); + daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype)); + daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, i_defaclacl)); + daclinfo[i].rdefaclacl = pg_strdup(PQgetvalue(res, i, i_rdefaclacl)); + daclinfo[i].initdefaclacl = pg_strdup(PQgetvalue(res, i, i_initdefaclacl)); + daclinfo[i].initrdefaclacl = pg_strdup(PQgetvalue(res, i, i_initrdefaclacl)); + + /* Decide whether we want to dump it */ + selectDumpableDefaultACL(&(daclinfo[i]), dopt); + } + + PQclear(res); + + destroyPQExpBuffer(query); + + return daclinfo; +} + +/* + * dumpComment -- + * + * This routine is used to dump any comments associated with the + * object handed to this routine. The routine takes the object type + * and object name (ready to print, except for schema decoration), plus + * the namespace and owner of the object (for labeling the ArchiveEntry), + * plus catalog ID and subid which are the lookup key for pg_description, + * plus the dump ID for the object (for setting a dependency). + * If a matching pg_description entry is found, it is dumped. + * + * Note: in some cases, such as comments for triggers and rules, the "type" + * string really looks like, e.g., "TRIGGER name ON". This is a bit of a hack + * but it doesn't seem worth complicating the API for all callers to make + * it cleaner. + * + * Note: although this routine takes a dumpId for dependency purposes, + * that purpose is just to mark the dependency in the emitted dump file + * for possible future use by pg_restore. We do NOT use it for determining + * ordering of the comment in the dump file, because this routine is called + * after dependency sorting occurs. This routine should be called just after + * calling ArchiveEntry() for the specified object. + */ +static void +dumpComment(Archive *fout, const char *type, const char *name, + const char *namespace, const char *owner, + CatalogId catalogId, int subid, DumpId dumpId) +{ + DumpOptions *dopt = fout->dopt; + CommentItem *comments; + int ncomments; + + /* do nothing, if --no-comments is supplied */ + if (dopt->no_comments) + return; + + /* Comments are schema not data ... except blob comments are data */ + if (strcmp(type, "LARGE OBJECT") != 0) + { + if (dopt->dataOnly) + return; + } + else + { + /* We do dump blob comments in binary-upgrade mode */ + if (dopt->schemaOnly && !dopt->binary_upgrade) + return; + } + + /* Search for comments associated with catalogId, using table */ + ncomments = findComments(fout, catalogId.tableoid, catalogId.oid, + &comments); + + /* Is there one matching the subid? */ + while (ncomments > 0) + { + if (comments->objsubid == subid) + break; + comments++; + ncomments--; + } + + /* If a comment exists, build COMMENT ON statement */ + if (ncomments > 0) + { + PQExpBuffer query = createPQExpBuffer(); + PQExpBuffer tag = createPQExpBuffer(); + + appendPQExpBuffer(query, "COMMENT ON %s ", type); + if (namespace && *namespace) + appendPQExpBuffer(query, "%s.", fmtId(namespace)); + appendPQExpBuffer(query, "%s IS ", name); + appendStringLiteralAH(query, comments->descr, fout); + appendPQExpBufferStr(query, ";\n"); + + appendPQExpBuffer(tag, "%s %s", type, name); + + /* + * We mark comments as SECTION_NONE because they really belong in the + * same section as their parent, whether that is pre-data or + * post-data. + */ + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tag->data, + .namespace = namespace, + .owner = owner, + .description = "COMMENT", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &dumpId, + .nDeps = 1)); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(tag); + } +} + +/* + * dumpTableComment -- + * + * As above, but dump comments for both the specified table (or view) + * and its columns. + */ +static void +dumpTableComment(Archive *fout, const TableInfo *tbinfo, + const char *reltypename) +{ + DumpOptions *dopt = fout->dopt; + CommentItem *comments; + int ncomments; + PQExpBuffer query; + PQExpBuffer tag; + + /* do nothing, if --no-comments is supplied */ + if (dopt->no_comments) + return; + + /* Comments are SCHEMA not data */ + if (dopt->dataOnly) + return; + + /* Search for comments associated with relation, using table */ + ncomments = findComments(fout, + tbinfo->dobj.catId.tableoid, + tbinfo->dobj.catId.oid, + &comments); + + /* If comments exist, build COMMENT ON statements */ + if (ncomments <= 0) + return; + + query = createPQExpBuffer(); + tag = createPQExpBuffer(); + + while (ncomments > 0) + { + const char *descr = comments->descr; + int objsubid = comments->objsubid; + + if (objsubid == 0) + { + resetPQExpBuffer(tag); + appendPQExpBuffer(tag, "%s %s", reltypename, + fmtId(tbinfo->dobj.name)); + + resetPQExpBuffer(query); + appendPQExpBuffer(query, "COMMENT ON %s %s IS ", reltypename, + fmtQualifiedDumpable(tbinfo)); + appendStringLiteralAH(query, descr, fout); + appendPQExpBufferStr(query, ";\n"); + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tag->data, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "COMMENT", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + } + else if (objsubid > 0 && objsubid <= tbinfo->numatts) + { + resetPQExpBuffer(tag); + appendPQExpBuffer(tag, "COLUMN %s.", + fmtId(tbinfo->dobj.name)); + appendPQExpBufferStr(tag, fmtId(tbinfo->attnames[objsubid - 1])); + + resetPQExpBuffer(query); + appendPQExpBuffer(query, "COMMENT ON COLUMN %s.", + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(query, "%s IS ", + fmtId(tbinfo->attnames[objsubid - 1])); + appendStringLiteralAH(query, descr, fout); + appendPQExpBufferStr(query, ";\n"); + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tag->data, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "COMMENT", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + } + + comments++; + ncomments--; + } + + destroyPQExpBuffer(query); + destroyPQExpBuffer(tag); +} + +/* + * findComments -- + * + * Find the comment(s), if any, associated with the given object. All the + * objsubid values associated with the given classoid/objoid are found with + * one search. + */ +static int +findComments(Archive *fout, Oid classoid, Oid objoid, + CommentItem **items) +{ + /* static storage for table of comments */ + static CommentItem *comments = NULL; + static int ncomments = -1; + + CommentItem *middle = NULL; + CommentItem *low; + CommentItem *high; + int nmatch; + + /* Get comments if we didn't already */ + if (ncomments < 0) + ncomments = collectComments(fout, &comments); + + /* + * Do binary search to find some item matching the object. + */ + low = &comments[0]; + high = &comments[ncomments - 1]; + while (low <= high) + { + middle = low + (high - low) / 2; + + if (classoid < middle->classoid) + high = middle - 1; + else if (classoid > middle->classoid) + low = middle + 1; + else if (objoid < middle->objoid) + high = middle - 1; + else if (objoid > middle->objoid) + low = middle + 1; + else + break; /* found a match */ + } + + if (low > high) /* no matches */ + { + *items = NULL; + return 0; + } + + /* + * Now determine how many items match the object. The search loop + * invariant still holds: only items between low and high inclusive could + * match. + */ + nmatch = 1; + while (middle > low) + { + if (classoid != middle[-1].classoid || + objoid != middle[-1].objoid) + break; + middle--; + nmatch++; + } + + *items = middle; + + middle += nmatch; + while (middle <= high) + { + if (classoid != middle->classoid || + objoid != middle->objoid) + break; + middle++; + nmatch++; + } + + return nmatch; +} + +/* + * collectComments -- + * + * Construct a table of all comments available for database objects. + * We used to do per-object queries for the comments, but it's much faster + * to pull them all over at once, and on most databases the memory cost + * isn't high. + * + * The table is sorted by classoid/objid/objsubid for speed in lookup. + */ +static int +collectComments(Archive *fout, CommentItem **items) +{ + PGresult *res; + PQExpBuffer query; + int i_description; + int i_classoid; + int i_objoid; + int i_objsubid; + int ntups; + int i; + CommentItem *comments; + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid " + "FROM pg_catalog.pg_description " + "ORDER BY classoid, objoid, objsubid"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + /* Construct lookup table containing OIDs in numeric form */ + + i_description = PQfnumber(res, "description"); + i_classoid = PQfnumber(res, "classoid"); + i_objoid = PQfnumber(res, "objoid"); + i_objsubid = PQfnumber(res, "objsubid"); + + ntups = PQntuples(res); + + comments = (CommentItem *) pg_malloc(ntups * sizeof(CommentItem)); + + for (i = 0; i < ntups; i++) + { + comments[i].descr = PQgetvalue(res, i, i_description); + comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid)); + comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid)); + comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid)); + } + + /* Do NOT free the PGresult since we are keeping pointers into it */ + destroyPQExpBuffer(query); + + *items = comments; + return ntups; +} + +/* + * dumpDumpableObject + * + * This routine and its subsidiaries are responsible for creating + * ArchiveEntries (TOC objects) for each object to be dumped. + */ +static void +dumpDumpableObject(Archive *fout, const DumpableObject *dobj) +{ + switch (dobj->objType) + { + case DO_NAMESPACE: + dumpNamespace(fout, (const NamespaceInfo *) dobj); + break; + case DO_EXTENSION: + dumpExtension(fout, (const ExtensionInfo *) dobj); + break; + case DO_TYPE: + dumpType(fout, (const TypeInfo *) dobj); + break; + case DO_SHELL_TYPE: + dumpShellType(fout, (const ShellTypeInfo *) dobj); + break; + case DO_FUNC: + dumpFunc(fout, (const FuncInfo *) dobj); + break; + case DO_AGG: + dumpAgg(fout, (const AggInfo *) dobj); + break; + case DO_OPERATOR: + dumpOpr(fout, (const OprInfo *) dobj); + break; + case DO_ACCESS_METHOD: + dumpAccessMethod(fout, (const AccessMethodInfo *) dobj); + break; + case DO_OPCLASS: + dumpOpclass(fout, (const OpclassInfo *) dobj); + break; + case DO_OPFAMILY: + dumpOpfamily(fout, (const OpfamilyInfo *) dobj); + break; + case DO_COLLATION: + dumpCollation(fout, (const CollInfo *) dobj); + break; + case DO_CONVERSION: + dumpConversion(fout, (const ConvInfo *) dobj); + break; + case DO_TABLE: + dumpTable(fout, (const TableInfo *) dobj); + break; + case DO_TABLE_ATTACH: + dumpTableAttach(fout, (const TableAttachInfo *) dobj); + break; + case DO_ATTRDEF: + dumpAttrDef(fout, (const AttrDefInfo *) dobj); + break; + case DO_INDEX: + dumpIndex(fout, (const IndxInfo *) dobj); + break; + case DO_INDEX_ATTACH: + dumpIndexAttach(fout, (const IndexAttachInfo *) dobj); + break; + case DO_STATSEXT: + dumpStatisticsExt(fout, (const StatsExtInfo *) dobj); + break; + case DO_REFRESH_MATVIEW: + refreshMatViewData(fout, (const TableDataInfo *) dobj); + break; + case DO_RULE: + dumpRule(fout, (const RuleInfo *) dobj); + break; + case DO_TRIGGER: + dumpTrigger(fout, (const TriggerInfo *) dobj); + break; + case DO_EVENT_TRIGGER: + dumpEventTrigger(fout, (const EventTriggerInfo *) dobj); + break; + case DO_CONSTRAINT: + dumpConstraint(fout, (const ConstraintInfo *) dobj); + break; + case DO_FK_CONSTRAINT: + dumpConstraint(fout, (const ConstraintInfo *) dobj); + break; + case DO_PROCLANG: + dumpProcLang(fout, (const ProcLangInfo *) dobj); + break; + case DO_CAST: + dumpCast(fout, (const CastInfo *) dobj); + break; + case DO_TRANSFORM: + dumpTransform(fout, (const TransformInfo *) dobj); + break; + case DO_SEQUENCE_SET: + dumpSequenceData(fout, (const TableDataInfo *) dobj); + break; + case DO_TABLE_DATA: + dumpTableData(fout, (const TableDataInfo *) dobj); + break; + case DO_DUMMY_TYPE: + /* table rowtypes and array types are never dumped separately */ + break; + case DO_TSPARSER: + dumpTSParser(fout, (const TSParserInfo *) dobj); + break; + case DO_TSDICT: + dumpTSDictionary(fout, (const TSDictInfo *) dobj); + break; + case DO_TSTEMPLATE: + dumpTSTemplate(fout, (const TSTemplateInfo *) dobj); + break; + case DO_TSCONFIG: + dumpTSConfig(fout, (const TSConfigInfo *) dobj); + break; + case DO_FDW: + dumpForeignDataWrapper(fout, (const FdwInfo *) dobj); + break; + case DO_FOREIGN_SERVER: + dumpForeignServer(fout, (const ForeignServerInfo *) dobj); + break; + case DO_DEFAULT_ACL: + dumpDefaultACL(fout, (const DefaultACLInfo *) dobj); + break; + case DO_BLOB: + dumpBlob(fout, (const BlobInfo *) dobj); + break; + case DO_BLOB_DATA: + if (dobj->dump & DUMP_COMPONENT_DATA) + { + TocEntry *te; + + te = ArchiveEntry(fout, dobj->catId, dobj->dumpId, + ARCHIVE_OPTS(.tag = dobj->name, + .description = "BLOBS", + .section = SECTION_DATA, + .dumpFn = dumpBlobs)); + + /* + * Set the TocEntry's dataLength in case we are doing a + * parallel dump and want to order dump jobs by table size. + * (We need some size estimate for every TocEntry with a + * DataDumper function.) We don't currently have any cheap + * way to estimate the size of blobs, but it doesn't matter; + * let's just set the size to a large value so parallel dumps + * will launch this job first. If there's lots of blobs, we + * win, and if there aren't, we don't lose much. (If you want + * to improve on this, really what you should be thinking + * about is allowing blob dumping to be parallelized, not just + * getting a smarter estimate for the single TOC entry.) + */ + te->dataLength = MaxBlockNumber; + } + break; + case DO_POLICY: + dumpPolicy(fout, (const PolicyInfo *) dobj); + break; + case DO_PUBLICATION: + dumpPublication(fout, (const PublicationInfo *) dobj); + break; + case DO_PUBLICATION_REL: + dumpPublicationTable(fout, (const PublicationRelInfo *) dobj); + break; + case DO_SUBSCRIPTION: + dumpSubscription(fout, (const SubscriptionInfo *) dobj); + break; + case DO_PRE_DATA_BOUNDARY: + case DO_POST_DATA_BOUNDARY: + /* never dumped, nothing to do */ + break; + } +} + +/* + * dumpNamespace + * writes out to fout the queries to recreate a user-defined namespace + */ +static void +dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qnspname; + + /* Skip if not to be dumped */ + if (!nspinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qnspname = pg_strdup(fmtId(nspinfo->dobj.name)); + + appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname); + + appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &nspinfo->dobj, + "SCHEMA", qnspname, NULL); + + if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = nspinfo->dobj.name, + .owner = nspinfo->rolname, + .description = "SCHEMA", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Schema Comments and Security Labels */ + if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "SCHEMA", qnspname, + NULL, nspinfo->rolname, + nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId); + + if (nspinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "SCHEMA", qnspname, + NULL, nspinfo->rolname, + nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId); + + if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, nspinfo->dobj.dumpId, InvalidDumpId, "SCHEMA", + qnspname, NULL, NULL, + nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl, + nspinfo->initnspacl, nspinfo->initrnspacl); + + free(qnspname); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); +} + +/* + * dumpExtension + * writes out to fout the queries to recreate an extension + */ +static void +dumpExtension(Archive *fout, const ExtensionInfo *extinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qextname; + + /* Skip if not to be dumped */ + if (!extinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qextname = pg_strdup(fmtId(extinfo->dobj.name)); + + appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname); + + if (!dopt->binary_upgrade) + { + /* + * In a regular dump, we simply create the extension, intentionally + * not specifying a version, so that the destination installation's + * default version is used. + * + * Use of IF NOT EXISTS here is unlike our behavior for other object + * types; but there are various scenarios in which it's convenient to + * manually create the desired extension before restoring, so we + * prefer to allow it to exist already. + */ + appendPQExpBuffer(q, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s;\n", + qextname, fmtId(extinfo->namespace)); + } + else + { + /* + * In binary-upgrade mode, it's critical to reproduce the state of the + * database exactly, so our procedure is to create an empty extension, + * restore all the contained objects normally, and add them to the + * extension one by one. This function performs just the first of + * those steps. binary_upgrade_extension_member() takes care of + * adding member objects as they're created. + */ + int i; + int n; + + appendPQExpBufferStr(q, "-- For binary upgrade, create an empty extension and insert objects into it\n"); + + /* + * We unconditionally create the extension, so we must drop it if it + * exists. This could happen if the user deleted 'plpgsql' and then + * readded it, causing its oid to be greater than g_last_builtin_oid. + */ + appendPQExpBuffer(q, "DROP EXTENSION IF EXISTS %s;\n", qextname); + + appendPQExpBufferStr(q, + "SELECT pg_catalog.binary_upgrade_create_empty_extension("); + appendStringLiteralAH(q, extinfo->dobj.name, fout); + appendPQExpBufferStr(q, ", "); + appendStringLiteralAH(q, extinfo->namespace, fout); + appendPQExpBufferStr(q, ", "); + appendPQExpBuffer(q, "%s, ", extinfo->relocatable ? "true" : "false"); + appendStringLiteralAH(q, extinfo->extversion, fout); + appendPQExpBufferStr(q, ", "); + + /* + * Note that we're pushing extconfig (an OID array) back into + * pg_extension exactly as-is. This is OK because pg_class OIDs are + * preserved in binary upgrade. + */ + if (strlen(extinfo->extconfig) > 2) + appendStringLiteralAH(q, extinfo->extconfig, fout); + else + appendPQExpBufferStr(q, "NULL"); + appendPQExpBufferStr(q, ", "); + if (strlen(extinfo->extcondition) > 2) + appendStringLiteralAH(q, extinfo->extcondition, fout); + else + appendPQExpBufferStr(q, "NULL"); + appendPQExpBufferStr(q, ", "); + appendPQExpBufferStr(q, "ARRAY["); + n = 0; + for (i = 0; i < extinfo->dobj.nDeps; i++) + { + DumpableObject *extobj; + + extobj = findObjectByDumpId(extinfo->dobj.dependencies[i]); + if (extobj && extobj->objType == DO_EXTENSION) + { + if (n++ > 0) + appendPQExpBufferChar(q, ','); + appendStringLiteralAH(q, extobj->name, fout); + } + } + appendPQExpBufferStr(q, "]::pg_catalog.text[]"); + appendPQExpBufferStr(q, ");\n"); + } + + if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = extinfo->dobj.name, + .description = "EXTENSION", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Extension Comments and Security Labels */ + if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "EXTENSION", qextname, + NULL, "", + extinfo->dobj.catId, 0, extinfo->dobj.dumpId); + + if (extinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "EXTENSION", qextname, + NULL, "", + extinfo->dobj.catId, 0, extinfo->dobj.dumpId); + + free(qextname); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); +} + +/* + * dumpType + * writes out to fout the queries to recreate a user-defined type + */ +static void +dumpType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + + /* Skip if not to be dumped */ + if (!tyinfo->dobj.dump || dopt->dataOnly) + return; + + /* Dump out in proper style */ + if (tyinfo->typtype == TYPTYPE_BASE) + dumpBaseType(fout, tyinfo); + else if (tyinfo->typtype == TYPTYPE_DOMAIN) + dumpDomain(fout, tyinfo); + else if (tyinfo->typtype == TYPTYPE_COMPOSITE) + dumpCompositeType(fout, tyinfo); + else if (tyinfo->typtype == TYPTYPE_ENUM) + dumpEnumType(fout, tyinfo); + else if (tyinfo->typtype == TYPTYPE_RANGE) + dumpRangeType(fout, tyinfo); + else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined) + dumpUndefinedType(fout, tyinfo); + else + pg_log_warning("typtype of data type \"%s\" appears to be invalid", + tyinfo->dobj.name); +} + +/* + * dumpEnumType + * writes out to fout the queries to recreate a user-defined enum type + */ +static void +dumpEnumType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + int num, + i; + Oid enum_oid; + char *qtypname; + char *qualtypname; + char *label; + + if (fout->remoteVersion >= 90100) + appendPQExpBuffer(query, "SELECT oid, enumlabel " + "FROM pg_catalog.pg_enum " + "WHERE enumtypid = '%u'" + "ORDER BY enumsortorder", + tyinfo->dobj.catId.oid); + else + appendPQExpBuffer(query, "SELECT oid, enumlabel " + "FROM pg_catalog.pg_enum " + "WHERE enumtypid = '%u'" + "ORDER BY oid", + tyinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + num = PQntuples(res); + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + /* + * CASCADE shouldn't be required here as for normal types since the I/O + * functions are generic and do not get dropped. + */ + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + false, false); + + appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (", + qualtypname); + + if (!dopt->binary_upgrade) + { + /* Labels with server-assigned oids */ + for (i = 0; i < num; i++) + { + label = PQgetvalue(res, i, PQfnumber(res, "enumlabel")); + if (i > 0) + appendPQExpBufferChar(q, ','); + appendPQExpBufferStr(q, "\n "); + appendStringLiteralAH(q, label, fout); + } + } + + appendPQExpBufferStr(q, "\n);\n"); + + if (dopt->binary_upgrade) + { + /* Labels with dump-assigned (preserved) oids */ + for (i = 0; i < num; i++) + { + enum_oid = atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))); + label = PQgetvalue(res, i, PQfnumber(res, "enumlabel")); + + if (i == 0) + appendPQExpBufferStr(q, "\n-- For binary upgrade, must preserve pg_enum oids\n"); + appendPQExpBuffer(q, + "SELECT pg_catalog.binary_upgrade_set_next_pg_enum_oid('%u'::pg_catalog.oid);\n", + enum_oid); + appendPQExpBuffer(q, "ALTER TYPE %s ADD VALUE ", qualtypname); + appendStringLiteralAH(q, label, fout); + appendPQExpBufferStr(q, ";\n\n"); + } + } + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Type Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + PQclear(res); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); +} + +/* + * dumpRangeType + * writes out to fout the queries to recreate a user-defined range type + */ +static void +dumpRangeType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + Oid collationOid; + char *qtypname; + char *qualtypname; + char *procname; + + appendPQExpBuffer(query, + "SELECT "); + + if (fout->remoteVersion >= 140000) + appendPQExpBuffer(query, + "pg_catalog.format_type(rngmultitypid, NULL) AS rngmultitype, "); + else + appendPQExpBuffer(query, + "NULL AS rngmultitype, "); + + appendPQExpBuffer(query, + "pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, " + "opc.opcname AS opcname, " + "(SELECT nspname FROM pg_catalog.pg_namespace nsp " + " WHERE nsp.oid = opc.opcnamespace) AS opcnsp, " + "opc.opcdefault, " + "CASE WHEN rngcollation = st.typcollation THEN 0 " + " ELSE rngcollation END AS collation, " + "rngcanonical, rngsubdiff " + "FROM pg_catalog.pg_range r, pg_catalog.pg_type st, " + " pg_catalog.pg_opclass opc " + "WHERE st.oid = rngsubtype AND opc.oid = rngsubopc AND " + "rngtypid = '%u'", + tyinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + /* + * CASCADE shouldn't be required here as for normal types since the I/O + * functions are generic and do not get dropped. + */ + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + false, true); + + appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (", + qualtypname); + + appendPQExpBuffer(q, "\n subtype = %s", + PQgetvalue(res, 0, PQfnumber(res, "rngsubtype"))); + + if (!PQgetisnull(res, 0, PQfnumber(res, "rngmultitype"))) + appendPQExpBuffer(q, ",\n multirange_type_name = %s", + PQgetvalue(res, 0, PQfnumber(res, "rngmultitype"))); + + /* print subtype_opclass only if not default for subtype */ + if (PQgetvalue(res, 0, PQfnumber(res, "opcdefault"))[0] != 't') + { + char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname")); + char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp")); + + appendPQExpBuffer(q, ",\n subtype_opclass = %s.", + fmtId(nspname)); + appendPQExpBufferStr(q, fmtId(opcname)); + } + + collationOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "collation"))); + if (OidIsValid(collationOid)) + { + CollInfo *coll = findCollationByOid(collationOid); + + if (coll) + appendPQExpBuffer(q, ",\n collation = %s", + fmtQualifiedDumpable(coll)); + } + + procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical")); + if (strcmp(procname, "-") != 0) + appendPQExpBuffer(q, ",\n canonical = %s", procname); + + procname = PQgetvalue(res, 0, PQfnumber(res, "rngsubdiff")); + if (strcmp(procname, "-") != 0) + appendPQExpBuffer(q, ",\n subtype_diff = %s", procname); + + appendPQExpBufferStr(q, "\n);\n"); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Type Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + PQclear(res); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); +} + +/* + * dumpUndefinedType + * writes out to fout the queries to recreate a !typisdefined type + * + * This is a shell type, but we use different terminology to distinguish + * this case from where we have to emit a shell type definition to break + * circular dependencies. An undefined type shouldn't ever have anything + * depending on it. + */ +static void +dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + char *qtypname; + char *qualtypname; + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + false, false); + + appendPQExpBuffer(q, "CREATE TYPE %s;\n", + qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Type Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qtypname); + free(qualtypname); +} + +/* + * dumpBaseType + * writes out to fout the queries to recreate a user-defined base type + */ +static void +dumpBaseType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + char *qtypname; + char *qualtypname; + char *typlen; + char *typinput; + char *typoutput; + char *typreceive; + char *typsend; + char *typmodin; + char *typmodout; + char *typanalyze; + char *typsubscript; + Oid typreceiveoid; + Oid typsendoid; + Oid typmodinoid; + Oid typmodoutoid; + Oid typanalyzeoid; + Oid typsubscriptoid; + char *typcategory; + char *typispreferred; + char *typdelim; + char *typbyval; + char *typalign; + char *typstorage; + char *typcollatable; + char *typdefault; + bool typdefault_is_literal = false; + + /* Fetch type-specific details */ + appendPQExpBufferStr(query, "SELECT typlen, " + "typinput, typoutput, typreceive, typsend, " + "typreceive::pg_catalog.oid AS typreceiveoid, " + "typsend::pg_catalog.oid AS typsendoid, " + "typanalyze, " + "typanalyze::pg_catalog.oid AS typanalyzeoid, " + "typdelim, typbyval, typalign, typstorage, "); + + if (fout->remoteVersion >= 80300) + appendPQExpBufferStr(query, + "typmodin, typmodout, " + "typmodin::pg_catalog.oid AS typmodinoid, " + "typmodout::pg_catalog.oid AS typmodoutoid, "); + else + appendPQExpBufferStr(query, + "'-' AS typmodin, '-' AS typmodout, " + "0 AS typmodinoid, 0 AS typmodoutoid, "); + + if (fout->remoteVersion >= 80400) + appendPQExpBufferStr(query, + "typcategory, typispreferred, "); + else + appendPQExpBufferStr(query, + "'U' AS typcategory, false AS typispreferred, "); + + if (fout->remoteVersion >= 90100) + appendPQExpBufferStr(query, "(typcollation <> 0) AS typcollatable, "); + else + appendPQExpBufferStr(query, "false AS typcollatable, "); + + if (fout->remoteVersion >= 140000) + appendPQExpBufferStr(query, + "typsubscript, " + "typsubscript::pg_catalog.oid AS typsubscriptoid, "); + else + appendPQExpBufferStr(query, + "'-' AS typsubscript, 0 AS typsubscriptoid, "); + + /* Before 8.4, pg_get_expr does not allow 0 for its second arg */ + if (fout->remoteVersion >= 80400) + appendPQExpBufferStr(query, + "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "); + else + appendPQExpBufferStr(query, + "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "); + + appendPQExpBuffer(query, "FROM pg_catalog.pg_type " + "WHERE oid = '%u'::pg_catalog.oid", + tyinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen")); + typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput")); + typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput")); + typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive")); + typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend")); + typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin")); + typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout")); + typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze")); + typsubscript = PQgetvalue(res, 0, PQfnumber(res, "typsubscript")); + typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid"))); + typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid"))); + typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid"))); + typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid"))); + typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid"))); + typsubscriptoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsubscriptoid"))); + typcategory = PQgetvalue(res, 0, PQfnumber(res, "typcategory")); + typispreferred = PQgetvalue(res, 0, PQfnumber(res, "typispreferred")); + typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim")); + typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval")); + typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign")); + typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage")); + typcollatable = PQgetvalue(res, 0, PQfnumber(res, "typcollatable")); + if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin"))) + typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin")); + else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault"))) + { + typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault")); + typdefault_is_literal = true; /* it needs quotes */ + } + else + typdefault = NULL; + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + /* + * The reason we include CASCADE is that the circular dependency between + * the type and its I/O functions makes it impossible to drop the type any + * other way. + */ + appendPQExpBuffer(delq, "DROP TYPE %s CASCADE;\n", qualtypname); + + /* + * We might already have a shell type, but setting pg_type_oid is + * harmless, and in any case we'd better set the array type OID. + */ + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + false, false); + + appendPQExpBuffer(q, + "CREATE TYPE %s (\n" + " INTERNALLENGTH = %s", + qualtypname, + (strcmp(typlen, "-1") == 0) ? "variable" : typlen); + + /* regproc result is sufficiently quoted already */ + appendPQExpBuffer(q, ",\n INPUT = %s", typinput); + appendPQExpBuffer(q, ",\n OUTPUT = %s", typoutput); + if (OidIsValid(typreceiveoid)) + appendPQExpBuffer(q, ",\n RECEIVE = %s", typreceive); + if (OidIsValid(typsendoid)) + appendPQExpBuffer(q, ",\n SEND = %s", typsend); + if (OidIsValid(typmodinoid)) + appendPQExpBuffer(q, ",\n TYPMOD_IN = %s", typmodin); + if (OidIsValid(typmodoutoid)) + appendPQExpBuffer(q, ",\n TYPMOD_OUT = %s", typmodout); + if (OidIsValid(typanalyzeoid)) + appendPQExpBuffer(q, ",\n ANALYZE = %s", typanalyze); + + if (strcmp(typcollatable, "t") == 0) + appendPQExpBufferStr(q, ",\n COLLATABLE = true"); + + if (typdefault != NULL) + { + appendPQExpBufferStr(q, ",\n DEFAULT = "); + if (typdefault_is_literal) + appendStringLiteralAH(q, typdefault, fout); + else + appendPQExpBufferStr(q, typdefault); + } + + if (OidIsValid(typsubscriptoid)) + appendPQExpBuffer(q, ",\n SUBSCRIPT = %s", typsubscript); + + if (OidIsValid(tyinfo->typelem)) + appendPQExpBuffer(q, ",\n ELEMENT = %s", + getFormattedTypeName(fout, tyinfo->typelem, + zeroIsError)); + + if (strcmp(typcategory, "U") != 0) + { + appendPQExpBufferStr(q, ",\n CATEGORY = "); + appendStringLiteralAH(q, typcategory, fout); + } + + if (strcmp(typispreferred, "t") == 0) + appendPQExpBufferStr(q, ",\n PREFERRED = true"); + + if (typdelim && strcmp(typdelim, ",") != 0) + { + appendPQExpBufferStr(q, ",\n DELIMITER = "); + appendStringLiteralAH(q, typdelim, fout); + } + + if (*typalign == TYPALIGN_CHAR) + appendPQExpBufferStr(q, ",\n ALIGNMENT = char"); + else if (*typalign == TYPALIGN_SHORT) + appendPQExpBufferStr(q, ",\n ALIGNMENT = int2"); + else if (*typalign == TYPALIGN_INT) + appendPQExpBufferStr(q, ",\n ALIGNMENT = int4"); + else if (*typalign == TYPALIGN_DOUBLE) + appendPQExpBufferStr(q, ",\n ALIGNMENT = double"); + + if (*typstorage == TYPSTORAGE_PLAIN) + appendPQExpBufferStr(q, ",\n STORAGE = plain"); + else if (*typstorage == TYPSTORAGE_EXTERNAL) + appendPQExpBufferStr(q, ",\n STORAGE = external"); + else if (*typstorage == TYPSTORAGE_EXTENDED) + appendPQExpBufferStr(q, ",\n STORAGE = extended"); + else if (*typstorage == TYPSTORAGE_MAIN) + appendPQExpBufferStr(q, ",\n STORAGE = main"); + + if (strcmp(typbyval, "t") == 0) + appendPQExpBufferStr(q, ",\n PASSEDBYVALUE"); + + appendPQExpBufferStr(q, "\n);\n"); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Type Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + PQclear(res); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); +} + +/* + * dumpDomain + * writes out to fout the queries to recreate a user-defined domain + */ +static void +dumpDomain(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + int i; + char *qtypname; + char *qualtypname; + char *typnotnull; + char *typdefn; + char *typdefault; + Oid typcollation; + bool typdefault_is_literal = false; + + /* Fetch domain specific details */ + if (fout->remoteVersion >= 90100) + { + /* typcollation is new in 9.1 */ + appendPQExpBuffer(query, "SELECT t.typnotnull, " + "pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, " + "pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, " + "t.typdefault, " + "CASE WHEN t.typcollation <> u.typcollation " + "THEN t.typcollation ELSE 0 END AS typcollation " + "FROM pg_catalog.pg_type t " + "LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) " + "WHERE t.oid = '%u'::pg_catalog.oid", + tyinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, "SELECT typnotnull, " + "pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, " + "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, " + "typdefault, 0 AS typcollation " + "FROM pg_catalog.pg_type " + "WHERE oid = '%u'::pg_catalog.oid", + tyinfo->dobj.catId.oid); + } + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull")); + typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn")); + if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin"))) + typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin")); + else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault"))) + { + typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault")); + typdefault_is_literal = true; /* it needs quotes */ + } + else + typdefault = NULL; + typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation"))); + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + true, /* force array type */ + false); /* force multirange type */ + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + appendPQExpBuffer(q, + "CREATE DOMAIN %s AS %s", + qualtypname, + typdefn); + + /* Print collation only if different from base type's collation */ + if (OidIsValid(typcollation)) + { + CollInfo *coll; + + coll = findCollationByOid(typcollation); + if (coll) + appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll)); + } + + if (typnotnull[0] == 't') + appendPQExpBufferStr(q, " NOT NULL"); + + if (typdefault != NULL) + { + appendPQExpBufferStr(q, " DEFAULT "); + if (typdefault_is_literal) + appendStringLiteralAH(q, typdefault, fout); + else + appendPQExpBufferStr(q, typdefault); + } + + PQclear(res); + + /* + * Add any CHECK constraints for the domain + */ + for (i = 0; i < tyinfo->nDomChecks; i++) + { + ConstraintInfo *domcheck = &(tyinfo->domChecks[i]); + + if (!domcheck->separate) + appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s", + fmtId(domcheck->dobj.name), domcheck->condef); + } + + appendPQExpBufferStr(q, ";\n"); + + appendPQExpBuffer(delq, "DROP DOMAIN %s;\n", qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "DOMAIN", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "DOMAIN", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Domain Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "DOMAIN", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "DOMAIN", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + /* Dump any per-constraint comments */ + for (i = 0; i < tyinfo->nDomChecks; i++) + { + ConstraintInfo *domcheck = &(tyinfo->domChecks[i]); + PQExpBuffer conprefix = createPQExpBuffer(); + + appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN", + fmtId(domcheck->dobj.name)); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, conprefix->data, qtypname, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, + domcheck->dobj.catId, 0, tyinfo->dobj.dumpId); + + destroyPQExpBuffer(conprefix); + } + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); +} + +/* + * dumpCompositeType + * writes out to fout the queries to recreate a user-defined stand-alone + * composite type + */ +static void +dumpCompositeType(Archive *fout, const TypeInfo *tyinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer dropped = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + char *qtypname; + char *qualtypname; + int ntups; + int i_attname; + int i_atttypdefn; + int i_attlen; + int i_attalign; + int i_attisdropped; + int i_attcollation; + int i; + int actual_atts; + + /* Fetch type specific details */ + if (fout->remoteVersion >= 90100) + { + /* + * attcollation is new in 9.1. Since we only want to dump COLLATE + * clauses for attributes whose collation is different from their + * type's default, we use a CASE here to suppress uninteresting + * attcollations cheaply. atttypid will be 0 for dropped columns; + * collation does not matter for those. + */ + appendPQExpBuffer(query, "SELECT a.attname, " + "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " + "a.attlen, a.attalign, a.attisdropped, " + "CASE WHEN a.attcollation <> at.typcollation " + "THEN a.attcollation ELSE 0 END AS attcollation " + "FROM pg_catalog.pg_type ct " + "JOIN pg_catalog.pg_attribute a ON a.attrelid = ct.typrelid " + "LEFT JOIN pg_catalog.pg_type at ON at.oid = a.atttypid " + "WHERE ct.oid = '%u'::pg_catalog.oid " + "ORDER BY a.attnum ", + tyinfo->dobj.catId.oid); + } + else + { + /* + * Since ALTER TYPE could not drop columns until 9.1, attisdropped + * should always be false. + */ + appendPQExpBuffer(query, "SELECT a.attname, " + "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " + "a.attlen, a.attalign, a.attisdropped, " + "0 AS attcollation " + "FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a " + "WHERE ct.oid = '%u'::pg_catalog.oid " + "AND a.attrelid = ct.typrelid " + "ORDER BY a.attnum ", + tyinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_attname = PQfnumber(res, "attname"); + i_atttypdefn = PQfnumber(res, "atttypdefn"); + i_attlen = PQfnumber(res, "attlen"); + i_attalign = PQfnumber(res, "attalign"); + i_attisdropped = PQfnumber(res, "attisdropped"); + i_attcollation = PQfnumber(res, "attcollation"); + + if (dopt->binary_upgrade) + { + binary_upgrade_set_type_oids_by_type_oid(fout, q, + tyinfo->dobj.catId.oid, + false, false); + binary_upgrade_set_pg_class_oids(fout, q, tyinfo->typrelid, false); + } + + qtypname = pg_strdup(fmtId(tyinfo->dobj.name)); + qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo)); + + appendPQExpBuffer(q, "CREATE TYPE %s AS (", + qualtypname); + + actual_atts = 0; + for (i = 0; i < ntups; i++) + { + char *attname; + char *atttypdefn; + char *attlen; + char *attalign; + bool attisdropped; + Oid attcollation; + + attname = PQgetvalue(res, i, i_attname); + atttypdefn = PQgetvalue(res, i, i_atttypdefn); + attlen = PQgetvalue(res, i, i_attlen); + attalign = PQgetvalue(res, i, i_attalign); + attisdropped = (PQgetvalue(res, i, i_attisdropped)[0] == 't'); + attcollation = atooid(PQgetvalue(res, i, i_attcollation)); + + if (attisdropped && !dopt->binary_upgrade) + continue; + + /* Format properly if not first attr */ + if (actual_atts++ > 0) + appendPQExpBufferChar(q, ','); + appendPQExpBufferStr(q, "\n\t"); + + if (!attisdropped) + { + appendPQExpBuffer(q, "%s %s", fmtId(attname), atttypdefn); + + /* Add collation if not default for the column type */ + if (OidIsValid(attcollation)) + { + CollInfo *coll; + + coll = findCollationByOid(attcollation); + if (coll) + appendPQExpBuffer(q, " COLLATE %s", + fmtQualifiedDumpable(coll)); + } + } + else + { + /* + * This is a dropped attribute and we're in binary_upgrade mode. + * Insert a placeholder for it in the CREATE TYPE command, and set + * length and alignment with direct UPDATE to the catalogs + * afterwards. See similar code in dumpTableSchema(). + */ + appendPQExpBuffer(q, "%s INTEGER /* dummy */", fmtId(attname)); + + /* stash separately for insertion after the CREATE TYPE */ + appendPQExpBufferStr(dropped, + "\n-- For binary upgrade, recreate dropped column.\n"); + appendPQExpBuffer(dropped, "UPDATE pg_catalog.pg_attribute\n" + "SET attlen = %s, " + "attalign = '%s', attbyval = false\n" + "WHERE attname = ", attlen, attalign); + appendStringLiteralAH(dropped, attname, fout); + appendPQExpBufferStr(dropped, "\n AND attrelid = "); + appendStringLiteralAH(dropped, qualtypname, fout); + appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n"); + + appendPQExpBuffer(dropped, "ALTER TYPE %s ", + qualtypname); + appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n", + fmtId(attname)); + } + } + appendPQExpBufferStr(q, "\n);\n"); + appendPQExpBufferStr(q, dropped->data); + + appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tyinfo->dobj, + "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tyinfo->dobj.name, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + + /* Dump Type Comments and Security Labels */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "TYPE", qtypname, + tyinfo->dobj.namespace->dobj.name, tyinfo->rolname, + tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId); + + if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE", + qtypname, NULL, + tyinfo->dobj.namespace->dobj.name, + tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl, + tyinfo->inittypacl, tyinfo->initrtypacl); + + PQclear(res); + destroyPQExpBuffer(q); + destroyPQExpBuffer(dropped); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qtypname); + free(qualtypname); + + /* Dump any per-column comments */ + if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpCompositeTypeColComments(fout, tyinfo); +} + +/* + * dumpCompositeTypeColComments + * writes out to fout the queries to recreate comments on the columns of + * a user-defined stand-alone composite type + */ +static void +dumpCompositeTypeColComments(Archive *fout, const TypeInfo *tyinfo) +{ + CommentItem *comments; + int ncomments; + PGresult *res; + PQExpBuffer query; + PQExpBuffer target; + Oid pgClassOid; + int i; + int ntups; + int i_attname; + int i_attnum; + + /* do nothing, if --no-comments is supplied */ + if (fout->dopt->no_comments) + return; + + query = createPQExpBuffer(); + + appendPQExpBuffer(query, + "SELECT c.tableoid, a.attname, a.attnum " + "FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a " + "WHERE c.oid = '%u' AND c.oid = a.attrelid " + " AND NOT a.attisdropped " + "ORDER BY a.attnum ", + tyinfo->typrelid); + + /* Fetch column attnames */ + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + if (ntups < 1) + { + PQclear(res); + destroyPQExpBuffer(query); + return; + } + + pgClassOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "tableoid"))); + + /* Search for comments associated with type's pg_class OID */ + ncomments = findComments(fout, + pgClassOid, + tyinfo->typrelid, + &comments); + + /* If no comments exist, we're done */ + if (ncomments <= 0) + { + PQclear(res); + destroyPQExpBuffer(query); + return; + } + + /* Build COMMENT ON statements */ + target = createPQExpBuffer(); + + i_attnum = PQfnumber(res, "attnum"); + i_attname = PQfnumber(res, "attname"); + while (ncomments > 0) + { + const char *attname; + + attname = NULL; + for (i = 0; i < ntups; i++) + { + if (atoi(PQgetvalue(res, i, i_attnum)) == comments->objsubid) + { + attname = PQgetvalue(res, i, i_attname); + break; + } + } + if (attname) /* just in case we don't find it */ + { + const char *descr = comments->descr; + + resetPQExpBuffer(target); + appendPQExpBuffer(target, "COLUMN %s.", + fmtId(tyinfo->dobj.name)); + appendPQExpBufferStr(target, fmtId(attname)); + + resetPQExpBuffer(query); + appendPQExpBuffer(query, "COMMENT ON COLUMN %s.", + fmtQualifiedDumpable(tyinfo)); + appendPQExpBuffer(query, "%s IS ", fmtId(attname)); + appendStringLiteralAH(query, descr, fout); + appendPQExpBufferStr(query, ";\n"); + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = target->data, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "COMMENT", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &(tyinfo->dobj.dumpId), + .nDeps = 1)); + } + + comments++; + ncomments--; + } + + PQclear(res); + destroyPQExpBuffer(query); + destroyPQExpBuffer(target); +} + +/* + * dumpShellType + * writes out to fout the queries to create a shell type + * + * We dump a shell definition in advance of the I/O functions for the type. + */ +static void +dumpShellType(Archive *fout, const ShellTypeInfo *stinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + + /* Skip if not to be dumped */ + if (!stinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + + /* + * Note the lack of a DROP command for the shell type; any required DROP + * is driven off the base type entry, instead. This interacts with + * _printTocEntry()'s use of the presence of a DROP command to decide + * whether an entry needs an ALTER OWNER command. We don't want to alter + * the shell type's owner immediately on creation; that should happen only + * after it's filled in, otherwise the backend complains. + */ + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_type_oid(fout, q, + stinfo->baseType->dobj.catId.oid, + false, false); + + appendPQExpBuffer(q, "CREATE TYPE %s;\n", + fmtQualifiedDumpable(stinfo)); + + if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = stinfo->dobj.name, + .namespace = stinfo->dobj.namespace->dobj.name, + .owner = stinfo->baseType->rolname, + .description = "SHELL TYPE", + .section = SECTION_PRE_DATA, + .createStmt = q->data)); + + destroyPQExpBuffer(q); +} + +/* + * dumpProcLang + * writes out to fout the queries to recreate a user-defined + * procedural language + */ +static void +dumpProcLang(Archive *fout, const ProcLangInfo *plang) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer defqry; + PQExpBuffer delqry; + bool useParams; + char *qlanname; + FuncInfo *funcInfo; + FuncInfo *inlineInfo = NULL; + FuncInfo *validatorInfo = NULL; + + /* Skip if not to be dumped */ + if (!plang->dobj.dump || dopt->dataOnly) + return; + + /* + * Try to find the support function(s). It is not an error if we don't + * find them --- if the functions are in the pg_catalog schema, as is + * standard in 8.1 and up, then we won't have loaded them. (In this case + * we will emit a parameterless CREATE LANGUAGE command, which will + * require PL template knowledge in the backend to reload.) + */ + + funcInfo = findFuncByOid(plang->lanplcallfoid); + if (funcInfo != NULL && !funcInfo->dobj.dump) + funcInfo = NULL; /* treat not-dumped same as not-found */ + + if (OidIsValid(plang->laninline)) + { + inlineInfo = findFuncByOid(plang->laninline); + if (inlineInfo != NULL && !inlineInfo->dobj.dump) + inlineInfo = NULL; + } + + if (OidIsValid(plang->lanvalidator)) + { + validatorInfo = findFuncByOid(plang->lanvalidator); + if (validatorInfo != NULL && !validatorInfo->dobj.dump) + validatorInfo = NULL; + } + + /* + * If the functions are dumpable then emit a complete CREATE LANGUAGE with + * parameters. Otherwise, we'll write a parameterless command, which will + * be interpreted as CREATE EXTENSION. + */ + useParams = (funcInfo != NULL && + (inlineInfo != NULL || !OidIsValid(plang->laninline)) && + (validatorInfo != NULL || !OidIsValid(plang->lanvalidator))); + + defqry = createPQExpBuffer(); + delqry = createPQExpBuffer(); + + qlanname = pg_strdup(fmtId(plang->dobj.name)); + + appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n", + qlanname); + + if (useParams) + { + appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s", + plang->lanpltrusted ? "TRUSTED " : "", + qlanname); + appendPQExpBuffer(defqry, " HANDLER %s", + fmtQualifiedDumpable(funcInfo)); + if (OidIsValid(plang->laninline)) + appendPQExpBuffer(defqry, " INLINE %s", + fmtQualifiedDumpable(inlineInfo)); + if (OidIsValid(plang->lanvalidator)) + appendPQExpBuffer(defqry, " VALIDATOR %s", + fmtQualifiedDumpable(validatorInfo)); + } + else + { + /* + * If not dumping parameters, then use CREATE OR REPLACE so that the + * command will not fail if the language is preinstalled in the target + * database. + * + * Modern servers will interpret this as CREATE EXTENSION IF NOT + * EXISTS; perhaps we should emit that instead? But it might just add + * confusion. + */ + appendPQExpBuffer(defqry, "CREATE OR REPLACE PROCEDURAL LANGUAGE %s", + qlanname); + } + appendPQExpBufferStr(defqry, ";\n"); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(defqry, &plang->dobj, + "LANGUAGE", qlanname, NULL); + + if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId, + ARCHIVE_OPTS(.tag = plang->dobj.name, + .owner = plang->lanowner, + .description = "PROCEDURAL LANGUAGE", + .section = SECTION_PRE_DATA, + .createStmt = defqry->data, + .dropStmt = delqry->data, + )); + + /* Dump Proc Lang Comments and Security Labels */ + if (plang->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "LANGUAGE", qlanname, + NULL, plang->lanowner, + plang->dobj.catId, 0, plang->dobj.dumpId); + + if (plang->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "LANGUAGE", qlanname, + NULL, plang->lanowner, + plang->dobj.catId, 0, plang->dobj.dumpId); + + if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, plang->dobj.dumpId, InvalidDumpId, "LANGUAGE", + qlanname, NULL, NULL, + plang->lanowner, plang->lanacl, plang->rlanacl, + plang->initlanacl, plang->initrlanacl); + + free(qlanname); + + destroyPQExpBuffer(defqry); + destroyPQExpBuffer(delqry); +} + +/* + * format_function_arguments: generate function name and argument list + * + * This is used when we can rely on pg_get_function_arguments to format + * the argument list. Note, however, that pg_get_function_arguments + * does not special-case zero-argument aggregates. + */ +static char * +format_function_arguments(const FuncInfo *finfo, const char *funcargs, bool is_agg) +{ + PQExpBufferData fn; + + initPQExpBuffer(&fn); + appendPQExpBufferStr(&fn, fmtId(finfo->dobj.name)); + if (is_agg && finfo->nargs == 0) + appendPQExpBufferStr(&fn, "(*)"); + else + appendPQExpBuffer(&fn, "(%s)", funcargs); + return fn.data; +} + +/* + * format_function_arguments_old: generate function name and argument list + * + * The argument type names are qualified if needed. The function name + * is never qualified. + * + * This is used only with pre-8.4 servers, so we aren't expecting to see + * VARIADIC or TABLE arguments, nor are there any defaults for arguments. + * + * Any or all of allargtypes, argmodes, argnames may be NULL. + */ +static char * +format_function_arguments_old(Archive *fout, + const FuncInfo *finfo, int nallargs, + char **allargtypes, + char **argmodes, + char **argnames) +{ + PQExpBufferData fn; + int j; + + initPQExpBuffer(&fn); + appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name)); + for (j = 0; j < nallargs; j++) + { + Oid typid; + const char *typname; + const char *argmode; + const char *argname; + + typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j]; + typname = getFormattedTypeName(fout, typid, zeroIsError); + + if (argmodes) + { + switch (argmodes[j][0]) + { + case PROARGMODE_IN: + argmode = ""; + break; + case PROARGMODE_OUT: + argmode = "OUT "; + break; + case PROARGMODE_INOUT: + argmode = "INOUT "; + break; + default: + pg_log_warning("bogus value in proargmodes array"); + argmode = ""; + break; + } + } + else + argmode = ""; + + argname = argnames ? argnames[j] : (char *) NULL; + if (argname && argname[0] == '\0') + argname = NULL; + + appendPQExpBuffer(&fn, "%s%s%s%s%s", + (j > 0) ? ", " : "", + argmode, + argname ? fmtId(argname) : "", + argname ? " " : "", + typname); + } + appendPQExpBufferChar(&fn, ')'); + return fn.data; +} + +/* + * format_function_signature: generate function name and argument list + * + * This is like format_function_arguments_old except that only a minimal + * list of input argument types is generated; this is sufficient to + * reference the function, but not to define it. + * + * If honor_quotes is false then the function name is never quoted. + * This is appropriate for use in TOC tags, but not in SQL commands. + */ +static char * +format_function_signature(Archive *fout, const FuncInfo *finfo, bool honor_quotes) +{ + PQExpBufferData fn; + int j; + + initPQExpBuffer(&fn); + if (honor_quotes) + appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name)); + else + appendPQExpBuffer(&fn, "%s(", finfo->dobj.name); + for (j = 0; j < finfo->nargs; j++) + { + if (j > 0) + appendPQExpBufferStr(&fn, ", "); + + appendPQExpBufferStr(&fn, + getFormattedTypeName(fout, finfo->argtypes[j], + zeroIsError)); + } + appendPQExpBufferChar(&fn, ')'); + return fn.data; +} + + +/* + * dumpFunc: + * dump out one function + */ +static void +dumpFunc(Archive *fout, const FuncInfo *finfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delqry; + PQExpBuffer asPart; + PGresult *res; + char *funcsig; /* identity signature */ + char *funcfullsig = NULL; /* full signature */ + char *funcsig_tag; + char *proretset; + char *prosrc; + char *probin; + char *prosqlbody; + char *funcargs; + char *funciargs; + char *funcresult; + char *proallargtypes; + char *proargmodes; + char *proargnames; + char *protrftypes; + char *prokind; + char *provolatile; + char *proisstrict; + char *prosecdef; + char *proleakproof; + char *proconfig; + char *procost; + char *prorows; + char *prosupport; + char *proparallel; + char *lanname; + int nallargs; + char **allargtypes = NULL; + char **argmodes = NULL; + char **argnames = NULL; + char **configitems = NULL; + int nconfigitems = 0; + const char *keyword; + int i; + + /* Skip if not to be dumped */ + if (!finfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delqry = createPQExpBuffer(); + asPart = createPQExpBuffer(); + + /* Fetch function-specific details */ + appendPQExpBufferStr(query, + "SELECT\n" + "proretset,\n" + "prosrc,\n" + "probin,\n" + "provolatile,\n" + "proisstrict,\n" + "prosecdef,\n" + "lanname,\n"); + + if (fout->remoteVersion >= 80300) + appendPQExpBufferStr(query, + "proconfig,\n" + "procost,\n" + "prorows,\n"); + else + appendPQExpBufferStr(query, + "null AS proconfig,\n" + "0 AS procost,\n" + "0 AS prorows,\n"); + + if (fout->remoteVersion >= 80400) + { + /* + * In 8.4 and up we rely on pg_get_function_arguments and + * pg_get_function_result instead of examining proallargtypes etc. + */ + appendPQExpBufferStr(query, + "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n" + "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n" + "pg_catalog.pg_get_function_result(p.oid) AS funcresult,\n"); + } + else if (fout->remoteVersion >= 80100) + appendPQExpBufferStr(query, + "proallargtypes,\n" + "proargmodes,\n" + "proargnames,\n"); + else + appendPQExpBufferStr(query, + "null AS proallargtypes,\n" + "null AS proargmodes,\n" + "proargnames,\n"); + + if (fout->remoteVersion >= 90200) + appendPQExpBufferStr(query, + "proleakproof,\n"); + else + appendPQExpBufferStr(query, + "false AS proleakproof,\n"); + + if (fout->remoteVersion >= 90500) + appendPQExpBufferStr(query, + "array_to_string(protrftypes, ' ') AS protrftypes,\n"); + + if (fout->remoteVersion >= 90600) + appendPQExpBufferStr(query, + "proparallel,\n"); + else + appendPQExpBufferStr(query, + "'u' AS proparallel,\n"); + + if (fout->remoteVersion >= 110000) + appendPQExpBufferStr(query, + "prokind,\n"); + else if (fout->remoteVersion >= 80400) + appendPQExpBufferStr(query, + "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind,\n"); + else + appendPQExpBufferStr(query, + "'f' AS prokind,\n"); + + if (fout->remoteVersion >= 120000) + appendPQExpBufferStr(query, + "prosupport,\n"); + else + appendPQExpBufferStr(query, + "'-' AS prosupport,\n"); + + if (fout->remoteVersion >= 140000) + appendPQExpBufferStr(query, + "pg_get_function_sqlbody(p.oid) AS prosqlbody\n"); + else + appendPQExpBufferStr(query, + "NULL AS prosqlbody\n"); + + appendPQExpBuffer(query, + "FROM pg_catalog.pg_proc p, pg_catalog.pg_language l\n" + "WHERE p.oid = '%u'::pg_catalog.oid " + "AND l.oid = p.prolang", + finfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset")); + if (PQgetisnull(res, 0, PQfnumber(res, "prosqlbody"))) + { + prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc")); + probin = PQgetvalue(res, 0, PQfnumber(res, "probin")); + prosqlbody = NULL; + } + else + { + prosrc = NULL; + probin = NULL; + prosqlbody = PQgetvalue(res, 0, PQfnumber(res, "prosqlbody")); + } + if (fout->remoteVersion >= 80400) + { + funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs")); + funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs")); + funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult")); + proallargtypes = proargmodes = proargnames = NULL; + } + else + { + proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes")); + proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes")); + proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames")); + funcargs = funciargs = funcresult = NULL; + } + if (PQfnumber(res, "protrftypes") != -1) + protrftypes = PQgetvalue(res, 0, PQfnumber(res, "protrftypes")); + else + protrftypes = NULL; + prokind = PQgetvalue(res, 0, PQfnumber(res, "prokind")); + provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile")); + proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict")); + prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef")); + proleakproof = PQgetvalue(res, 0, PQfnumber(res, "proleakproof")); + proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig")); + procost = PQgetvalue(res, 0, PQfnumber(res, "procost")); + prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows")); + prosupport = PQgetvalue(res, 0, PQfnumber(res, "prosupport")); + proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel")); + lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname")); + + /* + * See backend/commands/functioncmds.c for details of how the 'AS' clause + * is used. In 8.4 and up, an unused probin is NULL (here ""); previous + * versions would set it to "-". There are no known cases in which prosrc + * is unused, so the tests below for "-" are probably useless. + */ + if (prosqlbody) + { + appendPQExpBufferStr(asPart, prosqlbody); + } + else if (probin[0] != '\0' && strcmp(probin, "-") != 0) + { + appendPQExpBufferStr(asPart, "AS "); + appendStringLiteralAH(asPart, probin, fout); + if (strcmp(prosrc, "-") != 0) + { + appendPQExpBufferStr(asPart, ", "); + + /* + * where we have bin, use dollar quoting if allowed and src + * contains quote or backslash; else use regular quoting. + */ + if (dopt->disable_dollar_quoting || + (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL)) + appendStringLiteralAH(asPart, prosrc, fout); + else + appendStringLiteralDQ(asPart, prosrc, NULL); + } + } + else + { + if (strcmp(prosrc, "-") != 0) + { + appendPQExpBufferStr(asPart, "AS "); + /* with no bin, dollar quote src unconditionally if allowed */ + if (dopt->disable_dollar_quoting) + appendStringLiteralAH(asPart, prosrc, fout); + else + appendStringLiteralDQ(asPart, prosrc, NULL); + } + } + + nallargs = finfo->nargs; /* unless we learn different from allargs */ + + if (proallargtypes && *proallargtypes) + { + int nitems = 0; + + if (!parsePGArray(proallargtypes, &allargtypes, &nitems) || + nitems < finfo->nargs) + { + pg_log_warning("could not parse proallargtypes array"); + if (allargtypes) + free(allargtypes); + allargtypes = NULL; + } + else + nallargs = nitems; + } + + if (proargmodes && *proargmodes) + { + int nitems = 0; + + if (!parsePGArray(proargmodes, &argmodes, &nitems) || + nitems != nallargs) + { + pg_log_warning("could not parse proargmodes array"); + if (argmodes) + free(argmodes); + argmodes = NULL; + } + } + + if (proargnames && *proargnames) + { + int nitems = 0; + + if (!parsePGArray(proargnames, &argnames, &nitems) || + nitems != nallargs) + { + pg_log_warning("could not parse proargnames array"); + if (argnames) + free(argnames); + argnames = NULL; + } + } + + if (proconfig && *proconfig) + { + if (!parsePGArray(proconfig, &configitems, &nconfigitems)) + fatal("could not parse proconfig array"); + } + else + { + configitems = NULL; + nconfigitems = 0; + } + + if (funcargs) + { + /* 8.4 or later; we rely on server-side code for most of the work */ + funcfullsig = format_function_arguments(finfo, funcargs, false); + funcsig = format_function_arguments(finfo, funciargs, false); + } + else + /* pre-8.4, do it ourselves */ + funcsig = format_function_arguments_old(fout, + finfo, nallargs, allargtypes, + argmodes, argnames); + + funcsig_tag = format_function_signature(fout, finfo, false); + + if (prokind[0] == PROKIND_PROCEDURE) + keyword = "PROCEDURE"; + else + keyword = "FUNCTION"; /* works for window functions too */ + + appendPQExpBuffer(delqry, "DROP %s %s.%s;\n", + keyword, + fmtId(finfo->dobj.namespace->dobj.name), + funcsig); + + appendPQExpBuffer(q, "CREATE %s %s.%s", + keyword, + fmtId(finfo->dobj.namespace->dobj.name), + funcfullsig ? funcfullsig : + funcsig); + + if (prokind[0] == PROKIND_PROCEDURE) + /* no result type to output */ ; + else if (funcresult) + appendPQExpBuffer(q, " RETURNS %s", funcresult); + else + appendPQExpBuffer(q, " RETURNS %s%s", + (proretset[0] == 't') ? "SETOF " : "", + getFormattedTypeName(fout, finfo->prorettype, + zeroIsError)); + + appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname)); + + if (protrftypes != NULL && strcmp(protrftypes, "") != 0) + { + Oid *typeids = palloc(FUNC_MAX_ARGS * sizeof(Oid)); + int i; + + appendPQExpBufferStr(q, " TRANSFORM "); + parseOidArray(protrftypes, typeids, FUNC_MAX_ARGS); + for (i = 0; typeids[i]; i++) + { + if (i != 0) + appendPQExpBufferStr(q, ", "); + appendPQExpBuffer(q, "FOR TYPE %s", + getFormattedTypeName(fout, typeids[i], zeroAsNone)); + } + } + + if (prokind[0] == PROKIND_WINDOW) + appendPQExpBufferStr(q, " WINDOW"); + + if (provolatile[0] != PROVOLATILE_VOLATILE) + { + if (provolatile[0] == PROVOLATILE_IMMUTABLE) + appendPQExpBufferStr(q, " IMMUTABLE"); + else if (provolatile[0] == PROVOLATILE_STABLE) + appendPQExpBufferStr(q, " STABLE"); + else if (provolatile[0] != PROVOLATILE_VOLATILE) + fatal("unrecognized provolatile value for function \"%s\"", + finfo->dobj.name); + } + + if (proisstrict[0] == 't') + appendPQExpBufferStr(q, " STRICT"); + + if (prosecdef[0] == 't') + appendPQExpBufferStr(q, " SECURITY DEFINER"); + + if (proleakproof[0] == 't') + appendPQExpBufferStr(q, " LEAKPROOF"); + + /* + * COST and ROWS are emitted only if present and not default, so as not to + * break backwards-compatibility of the dump without need. Keep this code + * in sync with the defaults in functioncmds.c. + */ + if (strcmp(procost, "0") != 0) + { + if (strcmp(lanname, "internal") == 0 || strcmp(lanname, "c") == 0) + { + /* default cost is 1 */ + if (strcmp(procost, "1") != 0) + appendPQExpBuffer(q, " COST %s", procost); + } + else + { + /* default cost is 100 */ + if (strcmp(procost, "100") != 0) + appendPQExpBuffer(q, " COST %s", procost); + } + } + if (proretset[0] == 't' && + strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0) + appendPQExpBuffer(q, " ROWS %s", prorows); + + if (strcmp(prosupport, "-") != 0) + { + /* We rely on regprocout to provide quoting and qualification */ + appendPQExpBuffer(q, " SUPPORT %s", prosupport); + } + + if (proparallel[0] != PROPARALLEL_UNSAFE) + { + if (proparallel[0] == PROPARALLEL_SAFE) + appendPQExpBufferStr(q, " PARALLEL SAFE"); + else if (proparallel[0] == PROPARALLEL_RESTRICTED) + appendPQExpBufferStr(q, " PARALLEL RESTRICTED"); + else if (proparallel[0] != PROPARALLEL_UNSAFE) + fatal("unrecognized proparallel value for function \"%s\"", + finfo->dobj.name); + } + + for (i = 0; i < nconfigitems; i++) + { + /* we feel free to scribble on configitems[] here */ + char *configitem = configitems[i]; + char *pos; + + pos = strchr(configitem, '='); + if (pos == NULL) + continue; + *pos++ = '\0'; + appendPQExpBuffer(q, "\n SET %s TO ", fmtId(configitem)); + + /* + * Variables that are marked GUC_LIST_QUOTE were already fully quoted + * by flatten_set_variable_args() before they were put into the + * proconfig array. However, because the quoting rules used there + * aren't exactly like SQL's, we have to break the list value apart + * and then quote the elements as string literals. (The elements may + * be double-quoted as-is, but we can't just feed them to the SQL + * parser; it would do the wrong thing with elements that are + * zero-length or longer than NAMEDATALEN.) + * + * Variables that are not so marked should just be emitted as simple + * string literals. If the variable is not known to + * variable_is_guc_list_quote(), we'll do that; this makes it unsafe + * to use GUC_LIST_QUOTE for extension variables. + */ + if (variable_is_guc_list_quote(configitem)) + { + char **namelist; + char **nameptr; + + /* Parse string into list of identifiers */ + /* this shouldn't fail really */ + if (SplitGUCList(pos, ',', &namelist)) + { + for (nameptr = namelist; *nameptr; nameptr++) + { + if (nameptr != namelist) + appendPQExpBufferStr(q, ", "); + appendStringLiteralAH(q, *nameptr, fout); + } + } + pg_free(namelist); + } + else + appendStringLiteralAH(q, pos, fout); + } + + appendPQExpBuffer(q, "\n %s;\n", asPart->data); + + append_depends_on_extension(fout, q, &finfo->dobj, + "pg_catalog.pg_proc", keyword, + psprintf("%s.%s", + fmtId(finfo->dobj.namespace->dobj.name), + funcsig)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &finfo->dobj, + keyword, funcsig, + finfo->dobj.namespace->dobj.name); + + if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = funcsig_tag, + .namespace = finfo->dobj.namespace->dobj.name, + .owner = finfo->rolname, + .description = keyword, + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delqry->data)); + + /* Dump Function Comments and Security Labels */ + if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, keyword, funcsig, + finfo->dobj.namespace->dobj.name, finfo->rolname, + finfo->dobj.catId, 0, finfo->dobj.dumpId); + + if (finfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, keyword, funcsig, + finfo->dobj.namespace->dobj.name, finfo->rolname, + finfo->dobj.catId, 0, finfo->dobj.dumpId); + + if (finfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, finfo->dobj.dumpId, InvalidDumpId, keyword, + funcsig, NULL, + finfo->dobj.namespace->dobj.name, + finfo->rolname, finfo->proacl, finfo->rproacl, + finfo->initproacl, finfo->initrproacl); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delqry); + destroyPQExpBuffer(asPart); + free(funcsig); + if (funcfullsig) + free(funcfullsig); + free(funcsig_tag); + if (allargtypes) + free(allargtypes); + if (argmodes) + free(argmodes); + if (argnames) + free(argnames); + if (configitems) + free(configitems); +} + + +/* + * Dump a user-defined cast + */ +static void +dumpCast(Archive *fout, const CastInfo *cast) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer defqry; + PQExpBuffer delqry; + PQExpBuffer labelq; + PQExpBuffer castargs; + FuncInfo *funcInfo = NULL; + const char *sourceType; + const char *targetType; + + /* Skip if not to be dumped */ + if (!cast->dobj.dump || dopt->dataOnly) + return; + + /* Cannot dump if we don't have the cast function's info */ + if (OidIsValid(cast->castfunc)) + { + funcInfo = findFuncByOid(cast->castfunc); + if (funcInfo == NULL) + fatal("could not find function definition for function with OID %u", + cast->castfunc); + } + + defqry = createPQExpBuffer(); + delqry = createPQExpBuffer(); + labelq = createPQExpBuffer(); + castargs = createPQExpBuffer(); + + sourceType = getFormattedTypeName(fout, cast->castsource, zeroAsNone); + targetType = getFormattedTypeName(fout, cast->casttarget, zeroAsNone); + appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n", + sourceType, targetType); + + appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ", + sourceType, targetType); + + switch (cast->castmethod) + { + case COERCION_METHOD_BINARY: + appendPQExpBufferStr(defqry, "WITHOUT FUNCTION"); + break; + case COERCION_METHOD_INOUT: + appendPQExpBufferStr(defqry, "WITH INOUT"); + break; + case COERCION_METHOD_FUNCTION: + if (funcInfo) + { + char *fsig = format_function_signature(fout, funcInfo, true); + + /* + * Always qualify the function name (format_function_signature + * won't qualify it). + */ + appendPQExpBuffer(defqry, "WITH FUNCTION %s.%s", + fmtId(funcInfo->dobj.namespace->dobj.name), fsig); + free(fsig); + } + else + pg_log_warning("bogus value in pg_cast.castfunc or pg_cast.castmethod field"); + break; + default: + pg_log_warning("bogus value in pg_cast.castmethod field"); + } + + if (cast->castcontext == 'a') + appendPQExpBufferStr(defqry, " AS ASSIGNMENT"); + else if (cast->castcontext == 'i') + appendPQExpBufferStr(defqry, " AS IMPLICIT"); + appendPQExpBufferStr(defqry, ";\n"); + + appendPQExpBuffer(labelq, "CAST (%s AS %s)", + sourceType, targetType); + + appendPQExpBuffer(castargs, "(%s AS %s)", + sourceType, targetType); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(defqry, &cast->dobj, + "CAST", castargs->data, NULL); + + if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId, + ARCHIVE_OPTS(.tag = labelq->data, + .description = "CAST", + .section = SECTION_PRE_DATA, + .createStmt = defqry->data, + .dropStmt = delqry->data)); + + /* Dump Cast Comments */ + if (cast->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "CAST", castargs->data, + NULL, "", + cast->dobj.catId, 0, cast->dobj.dumpId); + + destroyPQExpBuffer(defqry); + destroyPQExpBuffer(delqry); + destroyPQExpBuffer(labelq); + destroyPQExpBuffer(castargs); +} + +/* + * Dump a transform + */ +static void +dumpTransform(Archive *fout, const TransformInfo *transform) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer defqry; + PQExpBuffer delqry; + PQExpBuffer labelq; + PQExpBuffer transformargs; + FuncInfo *fromsqlFuncInfo = NULL; + FuncInfo *tosqlFuncInfo = NULL; + char *lanname; + const char *transformType; + + /* Skip if not to be dumped */ + if (!transform->dobj.dump || dopt->dataOnly) + return; + + /* Cannot dump if we don't have the transform functions' info */ + if (OidIsValid(transform->trffromsql)) + { + fromsqlFuncInfo = findFuncByOid(transform->trffromsql); + if (fromsqlFuncInfo == NULL) + fatal("could not find function definition for function with OID %u", + transform->trffromsql); + } + if (OidIsValid(transform->trftosql)) + { + tosqlFuncInfo = findFuncByOid(transform->trftosql); + if (tosqlFuncInfo == NULL) + fatal("could not find function definition for function with OID %u", + transform->trftosql); + } + + defqry = createPQExpBuffer(); + delqry = createPQExpBuffer(); + labelq = createPQExpBuffer(); + transformargs = createPQExpBuffer(); + + lanname = get_language_name(fout, transform->trflang); + transformType = getFormattedTypeName(fout, transform->trftype, zeroAsNone); + + appendPQExpBuffer(delqry, "DROP TRANSFORM FOR %s LANGUAGE %s;\n", + transformType, lanname); + + appendPQExpBuffer(defqry, "CREATE TRANSFORM FOR %s LANGUAGE %s (", + transformType, lanname); + + if (!transform->trffromsql && !transform->trftosql) + pg_log_warning("bogus transform definition, at least one of trffromsql and trftosql should be nonzero"); + + if (transform->trffromsql) + { + if (fromsqlFuncInfo) + { + char *fsig = format_function_signature(fout, fromsqlFuncInfo, true); + + /* + * Always qualify the function name (format_function_signature + * won't qualify it). + */ + appendPQExpBuffer(defqry, "FROM SQL WITH FUNCTION %s.%s", + fmtId(fromsqlFuncInfo->dobj.namespace->dobj.name), fsig); + free(fsig); + } + else + pg_log_warning("bogus value in pg_transform.trffromsql field"); + } + + if (transform->trftosql) + { + if (transform->trffromsql) + appendPQExpBufferStr(defqry, ", "); + + if (tosqlFuncInfo) + { + char *fsig = format_function_signature(fout, tosqlFuncInfo, true); + + /* + * Always qualify the function name (format_function_signature + * won't qualify it). + */ + appendPQExpBuffer(defqry, "TO SQL WITH FUNCTION %s.%s", + fmtId(tosqlFuncInfo->dobj.namespace->dobj.name), fsig); + free(fsig); + } + else + pg_log_warning("bogus value in pg_transform.trftosql field"); + } + + appendPQExpBufferStr(defqry, ");\n"); + + appendPQExpBuffer(labelq, "TRANSFORM FOR %s LANGUAGE %s", + transformType, lanname); + + appendPQExpBuffer(transformargs, "FOR %s LANGUAGE %s", + transformType, lanname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(defqry, &transform->dobj, + "TRANSFORM", transformargs->data, NULL); + + if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId, + ARCHIVE_OPTS(.tag = labelq->data, + .description = "TRANSFORM", + .section = SECTION_PRE_DATA, + .createStmt = defqry->data, + .dropStmt = delqry->data, + .deps = transform->dobj.dependencies, + .nDeps = transform->dobj.nDeps)); + + /* Dump Transform Comments */ + if (transform->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TRANSFORM", transformargs->data, + NULL, "", + transform->dobj.catId, 0, transform->dobj.dumpId); + + free(lanname); + destroyPQExpBuffer(defqry); + destroyPQExpBuffer(delqry); + destroyPQExpBuffer(labelq); + destroyPQExpBuffer(transformargs); +} + + +/* + * dumpOpr + * write out a single operator definition + */ +static void +dumpOpr(Archive *fout, const OprInfo *oprinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer oprid; + PQExpBuffer details; + PGresult *res; + int i_oprkind; + int i_oprcode; + int i_oprleft; + int i_oprright; + int i_oprcom; + int i_oprnegate; + int i_oprrest; + int i_oprjoin; + int i_oprcanmerge; + int i_oprcanhash; + char *oprkind; + char *oprcode; + char *oprleft; + char *oprright; + char *oprcom; + char *oprnegate; + char *oprrest; + char *oprjoin; + char *oprcanmerge; + char *oprcanhash; + char *oprregproc; + char *oprref; + + /* Skip if not to be dumped */ + if (!oprinfo->dobj.dump || dopt->dataOnly) + return; + + /* + * some operators are invalid because they were the result of user + * defining operators before commutators exist + */ + if (!OidIsValid(oprinfo->oprcode)) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + oprid = createPQExpBuffer(); + details = createPQExpBuffer(); + + if (fout->remoteVersion >= 80300) + { + appendPQExpBuffer(query, "SELECT oprkind, " + "oprcode::pg_catalog.regprocedure, " + "oprleft::pg_catalog.regtype, " + "oprright::pg_catalog.regtype, " + "oprcom, " + "oprnegate, " + "oprrest::pg_catalog.regprocedure, " + "oprjoin::pg_catalog.regprocedure, " + "oprcanmerge, oprcanhash " + "FROM pg_catalog.pg_operator " + "WHERE oid = '%u'::pg_catalog.oid", + oprinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, "SELECT oprkind, " + "oprcode::pg_catalog.regprocedure, " + "oprleft::pg_catalog.regtype, " + "oprright::pg_catalog.regtype, " + "oprcom, " + "oprnegate, " + "oprrest::pg_catalog.regprocedure, " + "oprjoin::pg_catalog.regprocedure, " + "(oprlsortop != 0) AS oprcanmerge, " + "oprcanhash " + "FROM pg_catalog.pg_operator " + "WHERE oid = '%u'::pg_catalog.oid", + oprinfo->dobj.catId.oid); + } + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_oprkind = PQfnumber(res, "oprkind"); + i_oprcode = PQfnumber(res, "oprcode"); + i_oprleft = PQfnumber(res, "oprleft"); + i_oprright = PQfnumber(res, "oprright"); + i_oprcom = PQfnumber(res, "oprcom"); + i_oprnegate = PQfnumber(res, "oprnegate"); + i_oprrest = PQfnumber(res, "oprrest"); + i_oprjoin = PQfnumber(res, "oprjoin"); + i_oprcanmerge = PQfnumber(res, "oprcanmerge"); + i_oprcanhash = PQfnumber(res, "oprcanhash"); + + oprkind = PQgetvalue(res, 0, i_oprkind); + oprcode = PQgetvalue(res, 0, i_oprcode); + oprleft = PQgetvalue(res, 0, i_oprleft); + oprright = PQgetvalue(res, 0, i_oprright); + oprcom = PQgetvalue(res, 0, i_oprcom); + oprnegate = PQgetvalue(res, 0, i_oprnegate); + oprrest = PQgetvalue(res, 0, i_oprrest); + oprjoin = PQgetvalue(res, 0, i_oprjoin); + oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge); + oprcanhash = PQgetvalue(res, 0, i_oprcanhash); + + /* In PG14 upwards postfix operator support does not exist anymore. */ + if (strcmp(oprkind, "r") == 0) + pg_log_warning("postfix operators are not supported anymore (operator \"%s\")", + oprcode); + + oprregproc = convertRegProcReference(oprcode); + if (oprregproc) + { + appendPQExpBuffer(details, " FUNCTION = %s", oprregproc); + free(oprregproc); + } + + appendPQExpBuffer(oprid, "%s (", + oprinfo->dobj.name); + + /* + * right unary means there's a left arg and left unary means there's a + * right arg. (Although the "r" case is dead code for PG14 and later, + * continue to support it in case we're dumping from an old server.) + */ + if (strcmp(oprkind, "r") == 0 || + strcmp(oprkind, "b") == 0) + { + appendPQExpBuffer(details, ",\n LEFTARG = %s", oprleft); + appendPQExpBufferStr(oprid, oprleft); + } + else + appendPQExpBufferStr(oprid, "NONE"); + + if (strcmp(oprkind, "l") == 0 || + strcmp(oprkind, "b") == 0) + { + appendPQExpBuffer(details, ",\n RIGHTARG = %s", oprright); + appendPQExpBuffer(oprid, ", %s)", oprright); + } + else + appendPQExpBufferStr(oprid, ", NONE)"); + + oprref = getFormattedOperatorName(oprcom); + if (oprref) + { + appendPQExpBuffer(details, ",\n COMMUTATOR = %s", oprref); + free(oprref); + } + + oprref = getFormattedOperatorName(oprnegate); + if (oprref) + { + appendPQExpBuffer(details, ",\n NEGATOR = %s", oprref); + free(oprref); + } + + if (strcmp(oprcanmerge, "t") == 0) + appendPQExpBufferStr(details, ",\n MERGES"); + + if (strcmp(oprcanhash, "t") == 0) + appendPQExpBufferStr(details, ",\n HASHES"); + + oprregproc = convertRegProcReference(oprrest); + if (oprregproc) + { + appendPQExpBuffer(details, ",\n RESTRICT = %s", oprregproc); + free(oprregproc); + } + + oprregproc = convertRegProcReference(oprjoin); + if (oprregproc) + { + appendPQExpBuffer(details, ",\n JOIN = %s", oprregproc); + free(oprregproc); + } + + appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n", + fmtId(oprinfo->dobj.namespace->dobj.name), + oprid->data); + + appendPQExpBuffer(q, "CREATE OPERATOR %s.%s (\n%s\n);\n", + fmtId(oprinfo->dobj.namespace->dobj.name), + oprinfo->dobj.name, details->data); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &oprinfo->dobj, + "OPERATOR", oprid->data, + oprinfo->dobj.namespace->dobj.name); + + if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = oprinfo->dobj.name, + .namespace = oprinfo->dobj.namespace->dobj.name, + .owner = oprinfo->rolname, + .description = "OPERATOR", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Operator Comments */ + if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "OPERATOR", oprid->data, + oprinfo->dobj.namespace->dobj.name, oprinfo->rolname, + oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(oprid); + destroyPQExpBuffer(details); +} + +/* + * Convert a function reference obtained from pg_operator + * + * Returns allocated string of what to print, or NULL if function references + * is InvalidOid. Returned string is expected to be free'd by the caller. + * + * The input is a REGPROCEDURE display; we have to strip the argument-types + * part. + */ +static char * +convertRegProcReference(const char *proc) +{ + char *name; + char *paren; + bool inquote; + + /* In all cases "-" means a null reference */ + if (strcmp(proc, "-") == 0) + return NULL; + + name = pg_strdup(proc); + /* find non-double-quoted left paren */ + inquote = false; + for (paren = name; *paren; paren++) + { + if (*paren == '(' && !inquote) + { + *paren = '\0'; + break; + } + if (*paren == '"') + inquote = !inquote; + } + return name; +} + +/* + * getFormattedOperatorName - retrieve the operator name for the + * given operator OID (presented in string form). + * + * Returns an allocated string, or NULL if the given OID is invalid. + * Caller is responsible for free'ing result string. + * + * What we produce has the format "OPERATOR(schema.oprname)". This is only + * useful in commands where the operator's argument types can be inferred from + * context. We always schema-qualify the name, though. The predecessor to + * this code tried to skip the schema qualification if possible, but that led + * to wrong results in corner cases, such as if an operator and its negator + * are in different schemas. + */ +static char * +getFormattedOperatorName(const char *oproid) +{ + OprInfo *oprInfo; + + /* In all cases "0" means a null reference */ + if (strcmp(oproid, "0") == 0) + return NULL; + + oprInfo = findOprByOid(atooid(oproid)); + if (oprInfo == NULL) + { + pg_log_warning("could not find operator with OID %s", + oproid); + return NULL; + } + + return psprintf("OPERATOR(%s.%s)", + fmtId(oprInfo->dobj.namespace->dobj.name), + oprInfo->dobj.name); +} + +/* + * Convert a function OID obtained from pg_ts_parser or pg_ts_template + * + * It is sufficient to use REGPROC rather than REGPROCEDURE, since the + * argument lists of these functions are predetermined. Note that the + * caller should ensure we are in the proper schema, because the results + * are search path dependent! + */ +static char * +convertTSFunction(Archive *fout, Oid funcOid) +{ + char *result; + char query[128]; + PGresult *res; + + snprintf(query, sizeof(query), + "SELECT '%u'::pg_catalog.regproc", funcOid); + res = ExecuteSqlQueryForSingleRow(fout, query); + + result = pg_strdup(PQgetvalue(res, 0, 0)); + + PQclear(res); + + return result; +} + +/* + * dumpAccessMethod + * write out a single access method definition + */ +static void +dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qamname; + + /* Skip if not to be dumped */ + if (!aminfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qamname = pg_strdup(fmtId(aminfo->dobj.name)); + + appendPQExpBuffer(q, "CREATE ACCESS METHOD %s ", qamname); + + switch (aminfo->amtype) + { + case AMTYPE_INDEX: + appendPQExpBufferStr(q, "TYPE INDEX "); + break; + case AMTYPE_TABLE: + appendPQExpBufferStr(q, "TYPE TABLE "); + break; + default: + pg_log_warning("invalid type \"%c\" of access method \"%s\"", + aminfo->amtype, qamname); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qamname); + return; + } + + appendPQExpBuffer(q, "HANDLER %s;\n", aminfo->amhandler); + + appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n", + qamname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &aminfo->dobj, + "ACCESS METHOD", qamname, NULL); + + if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = aminfo->dobj.name, + .description = "ACCESS METHOD", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Access Method Comments */ + if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "ACCESS METHOD", qamname, + NULL, "", + aminfo->dobj.catId, 0, aminfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qamname); +} + +/* + * dumpOpclass + * write out a single operator class definition + */ +static void +dumpOpclass(Archive *fout, const OpclassInfo *opcinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer nameusing; + PGresult *res; + int ntups; + int i_opcintype; + int i_opckeytype; + int i_opcdefault; + int i_opcfamily; + int i_opcfamilyname; + int i_opcfamilynsp; + int i_amname; + int i_amopstrategy; + int i_amopreqcheck; + int i_amopopr; + int i_sortfamily; + int i_sortfamilynsp; + int i_amprocnum; + int i_amproc; + int i_amproclefttype; + int i_amprocrighttype; + char *opcintype; + char *opckeytype; + char *opcdefault; + char *opcfamily; + char *opcfamilyname; + char *opcfamilynsp; + char *amname; + char *amopstrategy; + char *amopreqcheck; + char *amopopr; + char *sortfamily; + char *sortfamilynsp; + char *amprocnum; + char *amproc; + char *amproclefttype; + char *amprocrighttype; + bool needComma; + int i; + + /* Skip if not to be dumped */ + if (!opcinfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + nameusing = createPQExpBuffer(); + + /* Get additional fields from the pg_opclass row */ + if (fout->remoteVersion >= 80300) + { + appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, " + "opckeytype::pg_catalog.regtype, " + "opcdefault, opcfamily, " + "opfname AS opcfamilyname, " + "nspname AS opcfamilynsp, " + "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname " + "FROM pg_catalog.pg_opclass c " + "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily " + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace " + "WHERE c.oid = '%u'::pg_catalog.oid", + opcinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, " + "opckeytype::pg_catalog.regtype, " + "opcdefault, NULL AS opcfamily, " + "NULL AS opcfamilyname, " + "NULL AS opcfamilynsp, " + "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname " + "FROM pg_catalog.pg_opclass " + "WHERE oid = '%u'::pg_catalog.oid", + opcinfo->dobj.catId.oid); + } + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_opcintype = PQfnumber(res, "opcintype"); + i_opckeytype = PQfnumber(res, "opckeytype"); + i_opcdefault = PQfnumber(res, "opcdefault"); + i_opcfamily = PQfnumber(res, "opcfamily"); + i_opcfamilyname = PQfnumber(res, "opcfamilyname"); + i_opcfamilynsp = PQfnumber(res, "opcfamilynsp"); + i_amname = PQfnumber(res, "amname"); + + /* opcintype may still be needed after we PQclear res */ + opcintype = pg_strdup(PQgetvalue(res, 0, i_opcintype)); + opckeytype = PQgetvalue(res, 0, i_opckeytype); + opcdefault = PQgetvalue(res, 0, i_opcdefault); + /* opcfamily will still be needed after we PQclear res */ + opcfamily = pg_strdup(PQgetvalue(res, 0, i_opcfamily)); + opcfamilyname = PQgetvalue(res, 0, i_opcfamilyname); + opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp); + /* amname will still be needed after we PQclear res */ + amname = pg_strdup(PQgetvalue(res, 0, i_amname)); + + appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s", + fmtQualifiedDumpable(opcinfo)); + appendPQExpBuffer(delq, " USING %s;\n", + fmtId(amname)); + + /* Build the fixed portion of the CREATE command */ + appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ", + fmtQualifiedDumpable(opcinfo)); + if (strcmp(opcdefault, "t") == 0) + appendPQExpBufferStr(q, "DEFAULT "); + appendPQExpBuffer(q, "FOR TYPE %s USING %s", + opcintype, + fmtId(amname)); + if (strlen(opcfamilyname) > 0) + { + appendPQExpBufferStr(q, " FAMILY "); + appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp)); + appendPQExpBufferStr(q, fmtId(opcfamilyname)); + } + appendPQExpBufferStr(q, " AS\n "); + + needComma = false; + + if (strcmp(opckeytype, "-") != 0) + { + appendPQExpBuffer(q, "STORAGE %s", + opckeytype); + needComma = true; + } + + PQclear(res); + + /* + * Now fetch and print the OPERATOR entries (pg_amop rows). + * + * Print only those opfamily members that are tied to the opclass by + * pg_depend entries. + * + * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping an + * older server's opclass in which it is used. This is to avoid + * hard-to-detect breakage if a newer pg_dump is used to dump from an + * older server and then reload into that old version. This can go away + * once 8.3 is so old as to not be of interest to anyone. + */ + resetPQExpBuffer(query); + + if (fout->remoteVersion >= 90100) + { + appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "opfname AS sortfamily, " + "nspname AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON " + "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) " + "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily " + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace " + "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND amopfamily = '%s'::pg_catalog.oid " + "ORDER BY amopstrategy", + opcinfo->dobj.catId.oid, + opcfamily); + } + else if (fout->remoteVersion >= 80400) + { + appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "NULL AS sortfamily, " + "NULL AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass " + "AND objid = ao.oid " + "ORDER BY amopstrategy", + opcinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80300) + { + appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "NULL AS sortfamily, " + "NULL AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass " + "AND objid = ao.oid " + "ORDER BY amopstrategy", + opcinfo->dobj.catId.oid); + } + else + { + /* + * Here, we print all entries since there are no opfamilies and hence + * no loose operators to worry about. + */ + appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "NULL AS sortfamily, " + "NULL AS sortfamilynsp " + "FROM pg_catalog.pg_amop " + "WHERE amopclaid = '%u'::pg_catalog.oid " + "ORDER BY amopstrategy", + opcinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_amopstrategy = PQfnumber(res, "amopstrategy"); + i_amopreqcheck = PQfnumber(res, "amopreqcheck"); + i_amopopr = PQfnumber(res, "amopopr"); + i_sortfamily = PQfnumber(res, "sortfamily"); + i_sortfamilynsp = PQfnumber(res, "sortfamilynsp"); + + for (i = 0; i < ntups; i++) + { + amopstrategy = PQgetvalue(res, i, i_amopstrategy); + amopreqcheck = PQgetvalue(res, i, i_amopreqcheck); + amopopr = PQgetvalue(res, i, i_amopopr); + sortfamily = PQgetvalue(res, i, i_sortfamily); + sortfamilynsp = PQgetvalue(res, i, i_sortfamilynsp); + + if (needComma) + appendPQExpBufferStr(q, " ,\n "); + + appendPQExpBuffer(q, "OPERATOR %s %s", + amopstrategy, amopopr); + + if (strlen(sortfamily) > 0) + { + appendPQExpBufferStr(q, " FOR ORDER BY "); + appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); + appendPQExpBufferStr(q, fmtId(sortfamily)); + } + + if (strcmp(amopreqcheck, "t") == 0) + appendPQExpBufferStr(q, " RECHECK"); + + needComma = true; + } + + PQclear(res); + + /* + * Now fetch and print the FUNCTION entries (pg_amproc rows). + * + * Print only those opfamily members that are tied to the opclass by + * pg_depend entries. + * + * We print the amproclefttype/amprocrighttype even though in most cases + * the backend could deduce the right values, because of the corner case + * of a btree sort support function for a cross-type comparison. That's + * only allowed in 9.2 and later, but for simplicity print them in all + * versions that have the columns. + */ + resetPQExpBuffer(query); + + if (fout->remoteVersion >= 80300) + { + appendPQExpBuffer(query, "SELECT amprocnum, " + "amproc::pg_catalog.regprocedure, " + "amproclefttype::pg_catalog.regtype, " + "amprocrighttype::pg_catalog.regtype " + "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass " + "AND objid = ap.oid " + "ORDER BY amprocnum", + opcinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, "SELECT amprocnum, " + "amproc::pg_catalog.regprocedure, " + "'' AS amproclefttype, " + "'' AS amprocrighttype " + "FROM pg_catalog.pg_amproc " + "WHERE amopclaid = '%u'::pg_catalog.oid " + "ORDER BY amprocnum", + opcinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_amprocnum = PQfnumber(res, "amprocnum"); + i_amproc = PQfnumber(res, "amproc"); + i_amproclefttype = PQfnumber(res, "amproclefttype"); + i_amprocrighttype = PQfnumber(res, "amprocrighttype"); + + for (i = 0; i < ntups; i++) + { + amprocnum = PQgetvalue(res, i, i_amprocnum); + amproc = PQgetvalue(res, i, i_amproc); + amproclefttype = PQgetvalue(res, i, i_amproclefttype); + amprocrighttype = PQgetvalue(res, i, i_amprocrighttype); + + if (needComma) + appendPQExpBufferStr(q, " ,\n "); + + appendPQExpBuffer(q, "FUNCTION %s", amprocnum); + + if (*amproclefttype && *amprocrighttype) + appendPQExpBuffer(q, " (%s, %s)", amproclefttype, amprocrighttype); + + appendPQExpBuffer(q, " %s", amproc); + + needComma = true; + } + + PQclear(res); + + /* + * If needComma is still false it means we haven't added anything after + * the AS keyword. To avoid printing broken SQL, append a dummy STORAGE + * clause with the same datatype. This isn't sanctioned by the + * documentation, but actually DefineOpClass will treat it as a no-op. + */ + if (!needComma) + appendPQExpBuffer(q, "STORAGE %s", opcintype); + + appendPQExpBufferStr(q, ";\n"); + + appendPQExpBufferStr(nameusing, fmtId(opcinfo->dobj.name)); + appendPQExpBuffer(nameusing, " USING %s", + fmtId(amname)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &opcinfo->dobj, + "OPERATOR CLASS", nameusing->data, + opcinfo->dobj.namespace->dobj.name); + + if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = opcinfo->dobj.name, + .namespace = opcinfo->dobj.namespace->dobj.name, + .owner = opcinfo->rolname, + .description = "OPERATOR CLASS", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Operator Class Comments */ + if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "OPERATOR CLASS", nameusing->data, + opcinfo->dobj.namespace->dobj.name, opcinfo->rolname, + opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId); + + free(opcintype); + free(opcfamily); + free(amname); + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(nameusing); +} + +/* + * dumpOpfamily + * write out a single operator family definition + * + * Note: this also dumps any "loose" operator members that aren't bound to a + * specific opclass within the opfamily. + */ +static void +dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer nameusing; + PGresult *res; + PGresult *res_ops; + PGresult *res_procs; + int ntups; + int i_amname; + int i_amopstrategy; + int i_amopreqcheck; + int i_amopopr; + int i_sortfamily; + int i_sortfamilynsp; + int i_amprocnum; + int i_amproc; + int i_amproclefttype; + int i_amprocrighttype; + char *amname; + char *amopstrategy; + char *amopreqcheck; + char *amopopr; + char *sortfamily; + char *sortfamilynsp; + char *amprocnum; + char *amproc; + char *amproclefttype; + char *amprocrighttype; + bool needComma; + int i; + + /* Skip if not to be dumped */ + if (!opfinfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + nameusing = createPQExpBuffer(); + + /* + * Fetch only those opfamily members that are tied directly to the + * opfamily by pg_depend entries. + * + * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping an + * older server's opclass in which it is used. This is to avoid + * hard-to-detect breakage if a newer pg_dump is used to dump from an + * older server and then reload into that old version. This can go away + * once 8.3 is so old as to not be of interest to anyone. + */ + if (fout->remoteVersion >= 90100) + { + appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "opfname AS sortfamily, " + "nspname AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON " + "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) " + "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily " + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace " + "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND amopfamily = '%u'::pg_catalog.oid " + "ORDER BY amopstrategy", + opfinfo->dobj.catId.oid, + opfinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80400) + { + appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "NULL AS sortfamily, " + "NULL AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass " + "AND objid = ao.oid " + "ORDER BY amopstrategy", + opfinfo->dobj.catId.oid); + } + else + { + appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, " + "amopopr::pg_catalog.regoperator, " + "NULL AS sortfamily, " + "NULL AS sortfamilynsp " + "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass " + "AND objid = ao.oid " + "ORDER BY amopstrategy", + opfinfo->dobj.catId.oid); + } + + res_ops = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + resetPQExpBuffer(query); + + appendPQExpBuffer(query, "SELECT amprocnum, " + "amproc::pg_catalog.regprocedure, " + "amproclefttype::pg_catalog.regtype, " + "amprocrighttype::pg_catalog.regtype " + "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend " + "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass " + "AND refobjid = '%u'::pg_catalog.oid " + "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass " + "AND objid = ap.oid " + "ORDER BY amprocnum", + opfinfo->dobj.catId.oid); + + res_procs = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + /* Get additional fields from the pg_opfamily row */ + resetPQExpBuffer(query); + + appendPQExpBuffer(query, "SELECT " + "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname " + "FROM pg_catalog.pg_opfamily " + "WHERE oid = '%u'::pg_catalog.oid", + opfinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_amname = PQfnumber(res, "amname"); + + /* amname will still be needed after we PQclear res */ + amname = pg_strdup(PQgetvalue(res, 0, i_amname)); + + appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s", + fmtQualifiedDumpable(opfinfo)); + appendPQExpBuffer(delq, " USING %s;\n", + fmtId(amname)); + + /* Build the fixed portion of the CREATE command */ + appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s", + fmtQualifiedDumpable(opfinfo)); + appendPQExpBuffer(q, " USING %s;\n", + fmtId(amname)); + + PQclear(res); + + /* Do we need an ALTER to add loose members? */ + if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0) + { + appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s", + fmtQualifiedDumpable(opfinfo)); + appendPQExpBuffer(q, " USING %s ADD\n ", + fmtId(amname)); + + needComma = false; + + /* + * Now fetch and print the OPERATOR entries (pg_amop rows). + */ + ntups = PQntuples(res_ops); + + i_amopstrategy = PQfnumber(res_ops, "amopstrategy"); + i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck"); + i_amopopr = PQfnumber(res_ops, "amopopr"); + i_sortfamily = PQfnumber(res_ops, "sortfamily"); + i_sortfamilynsp = PQfnumber(res_ops, "sortfamilynsp"); + + for (i = 0; i < ntups; i++) + { + amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy); + amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck); + amopopr = PQgetvalue(res_ops, i, i_amopopr); + sortfamily = PQgetvalue(res_ops, i, i_sortfamily); + sortfamilynsp = PQgetvalue(res_ops, i, i_sortfamilynsp); + + if (needComma) + appendPQExpBufferStr(q, " ,\n "); + + appendPQExpBuffer(q, "OPERATOR %s %s", + amopstrategy, amopopr); + + if (strlen(sortfamily) > 0) + { + appendPQExpBufferStr(q, " FOR ORDER BY "); + appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp)); + appendPQExpBufferStr(q, fmtId(sortfamily)); + } + + if (strcmp(amopreqcheck, "t") == 0) + appendPQExpBufferStr(q, " RECHECK"); + + needComma = true; + } + + /* + * Now fetch and print the FUNCTION entries (pg_amproc rows). + */ + ntups = PQntuples(res_procs); + + i_amprocnum = PQfnumber(res_procs, "amprocnum"); + i_amproc = PQfnumber(res_procs, "amproc"); + i_amproclefttype = PQfnumber(res_procs, "amproclefttype"); + i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype"); + + for (i = 0; i < ntups; i++) + { + amprocnum = PQgetvalue(res_procs, i, i_amprocnum); + amproc = PQgetvalue(res_procs, i, i_amproc); + amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype); + amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype); + + if (needComma) + appendPQExpBufferStr(q, " ,\n "); + + appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s", + amprocnum, amproclefttype, amprocrighttype, + amproc); + + needComma = true; + } + + appendPQExpBufferStr(q, ";\n"); + } + + appendPQExpBufferStr(nameusing, fmtId(opfinfo->dobj.name)); + appendPQExpBuffer(nameusing, " USING %s", + fmtId(amname)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &opfinfo->dobj, + "OPERATOR FAMILY", nameusing->data, + opfinfo->dobj.namespace->dobj.name); + + if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = opfinfo->dobj.name, + .namespace = opfinfo->dobj.namespace->dobj.name, + .owner = opfinfo->rolname, + .description = "OPERATOR FAMILY", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Operator Family Comments */ + if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "OPERATOR FAMILY", nameusing->data, + opfinfo->dobj.namespace->dobj.name, opfinfo->rolname, + opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId); + + free(amname); + PQclear(res_ops); + PQclear(res_procs); + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(nameusing); +} + +/* + * dumpCollation + * write out a single collation definition + */ +static void +dumpCollation(Archive *fout, const CollInfo *collinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + char *qcollname; + PGresult *res; + int i_collprovider; + int i_collisdeterministic; + int i_collcollate; + int i_collctype; + const char *collprovider; + const char *collcollate; + const char *collctype; + + /* Skip if not to be dumped */ + if (!collinfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qcollname = pg_strdup(fmtId(collinfo->dobj.name)); + + /* Get collation-specific details */ + appendPQExpBufferStr(query, "SELECT "); + + if (fout->remoteVersion >= 100000) + appendPQExpBufferStr(query, + "collprovider, " + "collversion, "); + else + appendPQExpBufferStr(query, + "'c' AS collprovider, " + "NULL AS collversion, "); + + if (fout->remoteVersion >= 120000) + appendPQExpBufferStr(query, + "collisdeterministic, "); + else + appendPQExpBufferStr(query, + "true AS collisdeterministic, "); + + appendPQExpBuffer(query, + "collcollate, " + "collctype " + "FROM pg_catalog.pg_collation c " + "WHERE c.oid = '%u'::pg_catalog.oid", + collinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_collprovider = PQfnumber(res, "collprovider"); + i_collisdeterministic = PQfnumber(res, "collisdeterministic"); + i_collcollate = PQfnumber(res, "collcollate"); + i_collctype = PQfnumber(res, "collctype"); + + collprovider = PQgetvalue(res, 0, i_collprovider); + collcollate = PQgetvalue(res, 0, i_collcollate); + collctype = PQgetvalue(res, 0, i_collctype); + + appendPQExpBuffer(delq, "DROP COLLATION %s;\n", + fmtQualifiedDumpable(collinfo)); + + appendPQExpBuffer(q, "CREATE COLLATION %s (", + fmtQualifiedDumpable(collinfo)); + + appendPQExpBufferStr(q, "provider = "); + if (collprovider[0] == 'c') + appendPQExpBufferStr(q, "libc"); + else if (collprovider[0] == 'i') + appendPQExpBufferStr(q, "icu"); + else if (collprovider[0] == 'd') + /* to allow dumping pg_catalog; not accepted on input */ + appendPQExpBufferStr(q, "default"); + else + fatal("unrecognized collation provider: %s", + collprovider); + + if (strcmp(PQgetvalue(res, 0, i_collisdeterministic), "f") == 0) + appendPQExpBufferStr(q, ", deterministic = false"); + + if (strcmp(collcollate, collctype) == 0) + { + appendPQExpBufferStr(q, ", locale = "); + appendStringLiteralAH(q, collcollate, fout); + } + else + { + appendPQExpBufferStr(q, ", lc_collate = "); + appendStringLiteralAH(q, collcollate, fout); + appendPQExpBufferStr(q, ", lc_ctype = "); + appendStringLiteralAH(q, collctype, fout); + } + + /* + * For binary upgrade, carry over the collation version. For normal + * dump/restore, omit the version, so that it is computed upon restore. + */ + if (dopt->binary_upgrade) + { + int i_collversion; + + i_collversion = PQfnumber(res, "collversion"); + if (!PQgetisnull(res, 0, i_collversion)) + { + appendPQExpBufferStr(q, ", version = "); + appendStringLiteralAH(q, + PQgetvalue(res, 0, i_collversion), + fout); + } + } + + appendPQExpBufferStr(q, ");\n"); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &collinfo->dobj, + "COLLATION", qcollname, + collinfo->dobj.namespace->dobj.name); + + if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = collinfo->dobj.name, + .namespace = collinfo->dobj.namespace->dobj.name, + .owner = collinfo->rolname, + .description = "COLLATION", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Collation Comments */ + if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "COLLATION", qcollname, + collinfo->dobj.namespace->dobj.name, collinfo->rolname, + collinfo->dobj.catId, 0, collinfo->dobj.dumpId); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qcollname); +} + +/* + * dumpConversion + * write out a single conversion definition + */ +static void +dumpConversion(Archive *fout, const ConvInfo *convinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + char *qconvname; + PGresult *res; + int i_conforencoding; + int i_contoencoding; + int i_conproc; + int i_condefault; + const char *conforencoding; + const char *contoencoding; + const char *conproc; + bool condefault; + + /* Skip if not to be dumped */ + if (!convinfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qconvname = pg_strdup(fmtId(convinfo->dobj.name)); + + /* Get conversion-specific details */ + appendPQExpBuffer(query, "SELECT " + "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, " + "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, " + "conproc, condefault " + "FROM pg_catalog.pg_conversion c " + "WHERE c.oid = '%u'::pg_catalog.oid", + convinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_conforencoding = PQfnumber(res, "conforencoding"); + i_contoencoding = PQfnumber(res, "contoencoding"); + i_conproc = PQfnumber(res, "conproc"); + i_condefault = PQfnumber(res, "condefault"); + + conforencoding = PQgetvalue(res, 0, i_conforencoding); + contoencoding = PQgetvalue(res, 0, i_contoencoding); + conproc = PQgetvalue(res, 0, i_conproc); + condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't'); + + appendPQExpBuffer(delq, "DROP CONVERSION %s;\n", + fmtQualifiedDumpable(convinfo)); + + appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ", + (condefault) ? "DEFAULT " : "", + fmtQualifiedDumpable(convinfo)); + appendStringLiteralAH(q, conforencoding, fout); + appendPQExpBufferStr(q, " TO "); + appendStringLiteralAH(q, contoencoding, fout); + /* regproc output is already sufficiently quoted */ + appendPQExpBuffer(q, " FROM %s;\n", conproc); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &convinfo->dobj, + "CONVERSION", qconvname, + convinfo->dobj.namespace->dobj.name); + + if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = convinfo->dobj.name, + .namespace = convinfo->dobj.namespace->dobj.name, + .owner = convinfo->rolname, + .description = "CONVERSION", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Conversion Comments */ + if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "CONVERSION", qconvname, + convinfo->dobj.namespace->dobj.name, convinfo->rolname, + convinfo->dobj.catId, 0, convinfo->dobj.dumpId); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qconvname); +} + +/* + * format_aggregate_signature: generate aggregate name and argument list + * + * The argument type names are qualified if needed. The aggregate name + * is never qualified. + */ +static char * +format_aggregate_signature(const AggInfo *agginfo, Archive *fout, bool honor_quotes) +{ + PQExpBufferData buf; + int j; + + initPQExpBuffer(&buf); + if (honor_quotes) + appendPQExpBufferStr(&buf, fmtId(agginfo->aggfn.dobj.name)); + else + appendPQExpBufferStr(&buf, agginfo->aggfn.dobj.name); + + if (agginfo->aggfn.nargs == 0) + appendPQExpBufferStr(&buf, "(*)"); + else + { + appendPQExpBufferChar(&buf, '('); + for (j = 0; j < agginfo->aggfn.nargs; j++) + appendPQExpBuffer(&buf, "%s%s", + (j > 0) ? ", " : "", + getFormattedTypeName(fout, + agginfo->aggfn.argtypes[j], + zeroIsError)); + appendPQExpBufferChar(&buf, ')'); + } + return buf.data; +} + +/* + * dumpAgg + * write out a single aggregate definition + */ +static void +dumpAgg(Archive *fout, const AggInfo *agginfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer details; + char *aggsig; /* identity signature */ + char *aggfullsig = NULL; /* full signature */ + char *aggsig_tag; + PGresult *res; + int i_agginitval; + int i_aggminitval; + const char *aggtransfn; + const char *aggfinalfn; + const char *aggcombinefn; + const char *aggserialfn; + const char *aggdeserialfn; + const char *aggmtransfn; + const char *aggminvtransfn; + const char *aggmfinalfn; + bool aggfinalextra; + bool aggmfinalextra; + char aggfinalmodify; + char aggmfinalmodify; + const char *aggsortop; + char *aggsortconvop; + char aggkind; + const char *aggtranstype; + const char *aggtransspace; + const char *aggmtranstype; + const char *aggmtransspace; + const char *agginitval; + const char *aggminitval; + const char *proparallel; + char defaultfinalmodify; + + /* Skip if not to be dumped */ + if (!agginfo->aggfn.dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + details = createPQExpBuffer(); + + /* Get aggregate-specific details */ + appendPQExpBufferStr(query, + "SELECT\n" + "aggtransfn,\n" + "aggfinalfn,\n" + "aggtranstype::pg_catalog.regtype,\n" + "agginitval,\n"); + + if (fout->remoteVersion >= 80100) + appendPQExpBufferStr(query, + "aggsortop,\n"); + else + appendPQExpBufferStr(query, + "0 AS aggsortop,\n"); + + if (fout->remoteVersion >= 80400) + appendPQExpBufferStr(query, + "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n" + "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n"); + + if (fout->remoteVersion >= 90400) + appendPQExpBufferStr(query, + "aggkind,\n" + "aggmtransfn,\n" + "aggminvtransfn,\n" + "aggmfinalfn,\n" + "aggmtranstype::pg_catalog.regtype,\n" + "aggfinalextra,\n" + "aggmfinalextra,\n" + "aggtransspace,\n" + "aggmtransspace,\n" + "aggminitval,\n"); + else + appendPQExpBufferStr(query, + "'n' AS aggkind,\n" + "'-' AS aggmtransfn,\n" + "'-' AS aggminvtransfn,\n" + "'-' AS aggmfinalfn,\n" + "0 AS aggmtranstype,\n" + "false AS aggfinalextra,\n" + "false AS aggmfinalextra,\n" + "0 AS aggtransspace,\n" + "0 AS aggmtransspace,\n" + "NULL AS aggminitval,\n"); + + if (fout->remoteVersion >= 90600) + appendPQExpBufferStr(query, + "aggcombinefn,\n" + "aggserialfn,\n" + "aggdeserialfn,\n" + "proparallel,\n"); + else + appendPQExpBufferStr(query, + "'-' AS aggcombinefn,\n" + "'-' AS aggserialfn,\n" + "'-' AS aggdeserialfn,\n" + "'u' AS proparallel,\n"); + + if (fout->remoteVersion >= 110000) + appendPQExpBufferStr(query, + "aggfinalmodify,\n" + "aggmfinalmodify\n"); + else + appendPQExpBufferStr(query, + "'0' AS aggfinalmodify,\n" + "'0' AS aggmfinalmodify\n"); + + appendPQExpBuffer(query, + "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p " + "WHERE a.aggfnoid = p.oid " + "AND p.oid = '%u'::pg_catalog.oid", + agginfo->aggfn.dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_agginitval = PQfnumber(res, "agginitval"); + i_aggminitval = PQfnumber(res, "aggminitval"); + + aggtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggtransfn")); + aggfinalfn = PQgetvalue(res, 0, PQfnumber(res, "aggfinalfn")); + aggcombinefn = PQgetvalue(res, 0, PQfnumber(res, "aggcombinefn")); + aggserialfn = PQgetvalue(res, 0, PQfnumber(res, "aggserialfn")); + aggdeserialfn = PQgetvalue(res, 0, PQfnumber(res, "aggdeserialfn")); + aggmtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggmtransfn")); + aggminvtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggminvtransfn")); + aggmfinalfn = PQgetvalue(res, 0, PQfnumber(res, "aggmfinalfn")); + aggfinalextra = (PQgetvalue(res, 0, PQfnumber(res, "aggfinalextra"))[0] == 't'); + aggmfinalextra = (PQgetvalue(res, 0, PQfnumber(res, "aggmfinalextra"))[0] == 't'); + aggfinalmodify = PQgetvalue(res, 0, PQfnumber(res, "aggfinalmodify"))[0]; + aggmfinalmodify = PQgetvalue(res, 0, PQfnumber(res, "aggmfinalmodify"))[0]; + aggsortop = PQgetvalue(res, 0, PQfnumber(res, "aggsortop")); + aggkind = PQgetvalue(res, 0, PQfnumber(res, "aggkind"))[0]; + aggtranstype = PQgetvalue(res, 0, PQfnumber(res, "aggtranstype")); + aggtransspace = PQgetvalue(res, 0, PQfnumber(res, "aggtransspace")); + aggmtranstype = PQgetvalue(res, 0, PQfnumber(res, "aggmtranstype")); + aggmtransspace = PQgetvalue(res, 0, PQfnumber(res, "aggmtransspace")); + agginitval = PQgetvalue(res, 0, i_agginitval); + aggminitval = PQgetvalue(res, 0, i_aggminitval); + proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel")); + + if (fout->remoteVersion >= 80400) + { + /* 8.4 or later; we rely on server-side code for most of the work */ + char *funcargs; + char *funciargs; + + funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs")); + funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs")); + aggfullsig = format_function_arguments(&agginfo->aggfn, funcargs, true); + aggsig = format_function_arguments(&agginfo->aggfn, funciargs, true); + } + else + /* pre-8.4, do it ourselves */ + aggsig = format_aggregate_signature(agginfo, fout, true); + + aggsig_tag = format_aggregate_signature(agginfo, fout, false); + + /* identify default modify flag for aggkind (must match DefineAggregate) */ + defaultfinalmodify = (aggkind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE; + /* replace omitted flags for old versions */ + if (aggfinalmodify == '0') + aggfinalmodify = defaultfinalmodify; + if (aggmfinalmodify == '0') + aggmfinalmodify = defaultfinalmodify; + + /* regproc and regtype output is already sufficiently quoted */ + appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s", + aggtransfn, aggtranstype); + + if (strcmp(aggtransspace, "0") != 0) + { + appendPQExpBuffer(details, ",\n SSPACE = %s", + aggtransspace); + } + + if (!PQgetisnull(res, 0, i_agginitval)) + { + appendPQExpBufferStr(details, ",\n INITCOND = "); + appendStringLiteralAH(details, agginitval, fout); + } + + if (strcmp(aggfinalfn, "-") != 0) + { + appendPQExpBuffer(details, ",\n FINALFUNC = %s", + aggfinalfn); + if (aggfinalextra) + appendPQExpBufferStr(details, ",\n FINALFUNC_EXTRA"); + if (aggfinalmodify != defaultfinalmodify) + { + switch (aggfinalmodify) + { + case AGGMODIFY_READ_ONLY: + appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = READ_ONLY"); + break; + case AGGMODIFY_SHAREABLE: + appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = SHAREABLE"); + break; + case AGGMODIFY_READ_WRITE: + appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = READ_WRITE"); + break; + default: + fatal("unrecognized aggfinalmodify value for aggregate \"%s\"", + agginfo->aggfn.dobj.name); + break; + } + } + } + + if (strcmp(aggcombinefn, "-") != 0) + appendPQExpBuffer(details, ",\n COMBINEFUNC = %s", aggcombinefn); + + if (strcmp(aggserialfn, "-") != 0) + appendPQExpBuffer(details, ",\n SERIALFUNC = %s", aggserialfn); + + if (strcmp(aggdeserialfn, "-") != 0) + appendPQExpBuffer(details, ",\n DESERIALFUNC = %s", aggdeserialfn); + + if (strcmp(aggmtransfn, "-") != 0) + { + appendPQExpBuffer(details, ",\n MSFUNC = %s,\n MINVFUNC = %s,\n MSTYPE = %s", + aggmtransfn, + aggminvtransfn, + aggmtranstype); + } + + if (strcmp(aggmtransspace, "0") != 0) + { + appendPQExpBuffer(details, ",\n MSSPACE = %s", + aggmtransspace); + } + + if (!PQgetisnull(res, 0, i_aggminitval)) + { + appendPQExpBufferStr(details, ",\n MINITCOND = "); + appendStringLiteralAH(details, aggminitval, fout); + } + + if (strcmp(aggmfinalfn, "-") != 0) + { + appendPQExpBuffer(details, ",\n MFINALFUNC = %s", + aggmfinalfn); + if (aggmfinalextra) + appendPQExpBufferStr(details, ",\n MFINALFUNC_EXTRA"); + if (aggmfinalmodify != defaultfinalmodify) + { + switch (aggmfinalmodify) + { + case AGGMODIFY_READ_ONLY: + appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = READ_ONLY"); + break; + case AGGMODIFY_SHAREABLE: + appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = SHAREABLE"); + break; + case AGGMODIFY_READ_WRITE: + appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = READ_WRITE"); + break; + default: + fatal("unrecognized aggmfinalmodify value for aggregate \"%s\"", + agginfo->aggfn.dobj.name); + break; + } + } + } + + aggsortconvop = getFormattedOperatorName(aggsortop); + if (aggsortconvop) + { + appendPQExpBuffer(details, ",\n SORTOP = %s", + aggsortconvop); + free(aggsortconvop); + } + + if (aggkind == AGGKIND_HYPOTHETICAL) + appendPQExpBufferStr(details, ",\n HYPOTHETICAL"); + + if (proparallel[0] != PROPARALLEL_UNSAFE) + { + if (proparallel[0] == PROPARALLEL_SAFE) + appendPQExpBufferStr(details, ",\n PARALLEL = safe"); + else if (proparallel[0] == PROPARALLEL_RESTRICTED) + appendPQExpBufferStr(details, ",\n PARALLEL = restricted"); + else if (proparallel[0] != PROPARALLEL_UNSAFE) + fatal("unrecognized proparallel value for function \"%s\"", + agginfo->aggfn.dobj.name); + } + + appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n", + fmtId(agginfo->aggfn.dobj.namespace->dobj.name), + aggsig); + + appendPQExpBuffer(q, "CREATE AGGREGATE %s.%s (\n%s\n);\n", + fmtId(agginfo->aggfn.dobj.namespace->dobj.name), + aggfullsig ? aggfullsig : aggsig, details->data); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, + "AGGREGATE", aggsig, + agginfo->aggfn.dobj.namespace->dobj.name); + + if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, agginfo->aggfn.dobj.catId, + agginfo->aggfn.dobj.dumpId, + ARCHIVE_OPTS(.tag = aggsig_tag, + .namespace = agginfo->aggfn.dobj.namespace->dobj.name, + .owner = agginfo->aggfn.rolname, + .description = "AGGREGATE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Aggregate Comments */ + if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "AGGREGATE", aggsig, + agginfo->aggfn.dobj.namespace->dobj.name, + agginfo->aggfn.rolname, + agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId); + + if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "AGGREGATE", aggsig, + agginfo->aggfn.dobj.namespace->dobj.name, + agginfo->aggfn.rolname, + agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId); + + /* + * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL + * command look like a function's GRANT; in particular this affects the + * syntax for zero-argument aggregates and ordered-set aggregates. + */ + free(aggsig); + + aggsig = format_function_signature(fout, &agginfo->aggfn, true); + + if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, agginfo->aggfn.dobj.dumpId, InvalidDumpId, + "FUNCTION", aggsig, NULL, + agginfo->aggfn.dobj.namespace->dobj.name, + agginfo->aggfn.rolname, agginfo->aggfn.proacl, + agginfo->aggfn.rproacl, + agginfo->aggfn.initproacl, agginfo->aggfn.initrproacl); + + free(aggsig); + if (aggfullsig) + free(aggfullsig); + free(aggsig_tag); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(details); +} + +/* + * dumpTSParser + * write out a single text search parser + */ +static void +dumpTSParser(Archive *fout, const TSParserInfo *prsinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qprsname; + + /* Skip if not to be dumped */ + if (!prsinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qprsname = pg_strdup(fmtId(prsinfo->dobj.name)); + + appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n", + fmtQualifiedDumpable(prsinfo)); + + appendPQExpBuffer(q, " START = %s,\n", + convertTSFunction(fout, prsinfo->prsstart)); + appendPQExpBuffer(q, " GETTOKEN = %s,\n", + convertTSFunction(fout, prsinfo->prstoken)); + appendPQExpBuffer(q, " END = %s,\n", + convertTSFunction(fout, prsinfo->prsend)); + if (prsinfo->prsheadline != InvalidOid) + appendPQExpBuffer(q, " HEADLINE = %s,\n", + convertTSFunction(fout, prsinfo->prsheadline)); + appendPQExpBuffer(q, " LEXTYPES = %s );\n", + convertTSFunction(fout, prsinfo->prslextype)); + + appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s;\n", + fmtQualifiedDumpable(prsinfo)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &prsinfo->dobj, + "TEXT SEARCH PARSER", qprsname, + prsinfo->dobj.namespace->dobj.name); + + if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = prsinfo->dobj.name, + .namespace = prsinfo->dobj.namespace->dobj.name, + .description = "TEXT SEARCH PARSER", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Parser Comments */ + if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TEXT SEARCH PARSER", qprsname, + prsinfo->dobj.namespace->dobj.name, "", + prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qprsname); +} + +/* + * dumpTSDictionary + * write out a single text search dictionary + */ +static void +dumpTSDictionary(Archive *fout, const TSDictInfo *dictinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer query; + char *qdictname; + PGresult *res; + char *nspname; + char *tmplname; + + /* Skip if not to be dumped */ + if (!dictinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qdictname = pg_strdup(fmtId(dictinfo->dobj.name)); + + /* Fetch name and namespace of the dictionary's template */ + appendPQExpBuffer(query, "SELECT nspname, tmplname " + "FROM pg_ts_template p, pg_namespace n " + "WHERE p.oid = '%u' AND n.oid = tmplnamespace", + dictinfo->dicttemplate); + res = ExecuteSqlQueryForSingleRow(fout, query->data); + nspname = PQgetvalue(res, 0, 0); + tmplname = PQgetvalue(res, 0, 1); + + appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n", + fmtQualifiedDumpable(dictinfo)); + + appendPQExpBufferStr(q, " TEMPLATE = "); + appendPQExpBuffer(q, "%s.", fmtId(nspname)); + appendPQExpBufferStr(q, fmtId(tmplname)); + + PQclear(res); + + /* the dictinitoption can be dumped straight into the command */ + if (dictinfo->dictinitoption) + appendPQExpBuffer(q, ",\n %s", dictinfo->dictinitoption); + + appendPQExpBufferStr(q, " );\n"); + + appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s;\n", + fmtQualifiedDumpable(dictinfo)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &dictinfo->dobj, + "TEXT SEARCH DICTIONARY", qdictname, + dictinfo->dobj.namespace->dobj.name); + + if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = dictinfo->dobj.name, + .namespace = dictinfo->dobj.namespace->dobj.name, + .owner = dictinfo->rolname, + .description = "TEXT SEARCH DICTIONARY", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Dictionary Comments */ + if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TEXT SEARCH DICTIONARY", qdictname, + dictinfo->dobj.namespace->dobj.name, dictinfo->rolname, + dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qdictname); +} + +/* + * dumpTSTemplate + * write out a single text search template + */ +static void +dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qtmplname; + + /* Skip if not to be dumped */ + if (!tmplinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qtmplname = pg_strdup(fmtId(tmplinfo->dobj.name)); + + appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n", + fmtQualifiedDumpable(tmplinfo)); + + if (tmplinfo->tmplinit != InvalidOid) + appendPQExpBuffer(q, " INIT = %s,\n", + convertTSFunction(fout, tmplinfo->tmplinit)); + appendPQExpBuffer(q, " LEXIZE = %s );\n", + convertTSFunction(fout, tmplinfo->tmpllexize)); + + appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s;\n", + fmtQualifiedDumpable(tmplinfo)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tmplinfo->dobj, + "TEXT SEARCH TEMPLATE", qtmplname, + tmplinfo->dobj.namespace->dobj.name); + + if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tmplinfo->dobj.name, + .namespace = tmplinfo->dobj.namespace->dobj.name, + .description = "TEXT SEARCH TEMPLATE", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Template Comments */ + if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TEXT SEARCH TEMPLATE", qtmplname, + tmplinfo->dobj.namespace->dobj.name, "", + tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qtmplname); +} + +/* + * dumpTSConfig + * write out a single text search configuration + */ +static void +dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer query; + char *qcfgname; + PGresult *res; + char *nspname; + char *prsname; + int ntups, + i; + int i_tokenname; + int i_dictname; + + /* Skip if not to be dumped */ + if (!cfginfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qcfgname = pg_strdup(fmtId(cfginfo->dobj.name)); + + /* Fetch name and namespace of the config's parser */ + appendPQExpBuffer(query, "SELECT nspname, prsname " + "FROM pg_ts_parser p, pg_namespace n " + "WHERE p.oid = '%u' AND n.oid = prsnamespace", + cfginfo->cfgparser); + res = ExecuteSqlQueryForSingleRow(fout, query->data); + nspname = PQgetvalue(res, 0, 0); + prsname = PQgetvalue(res, 0, 1); + + appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n", + fmtQualifiedDumpable(cfginfo)); + + appendPQExpBuffer(q, " PARSER = %s.", fmtId(nspname)); + appendPQExpBuffer(q, "%s );\n", fmtId(prsname)); + + PQclear(res); + + resetPQExpBuffer(query); + appendPQExpBuffer(query, + "SELECT\n" + " ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t\n" + " WHERE t.tokid = m.maptokentype ) AS tokenname,\n" + " m.mapdict::pg_catalog.regdictionary AS dictname\n" + "FROM pg_catalog.pg_ts_config_map AS m\n" + "WHERE m.mapcfg = '%u'\n" + "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno", + cfginfo->cfgparser, cfginfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + ntups = PQntuples(res); + + i_tokenname = PQfnumber(res, "tokenname"); + i_dictname = PQfnumber(res, "dictname"); + + for (i = 0; i < ntups; i++) + { + char *tokenname = PQgetvalue(res, i, i_tokenname); + char *dictname = PQgetvalue(res, i, i_dictname); + + if (i == 0 || + strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0) + { + /* starting a new token type, so start a new command */ + if (i > 0) + appendPQExpBufferStr(q, ";\n"); + appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n", + fmtQualifiedDumpable(cfginfo)); + /* tokenname needs quoting, dictname does NOT */ + appendPQExpBuffer(q, " ADD MAPPING FOR %s WITH %s", + fmtId(tokenname), dictname); + } + else + appendPQExpBuffer(q, ", %s", dictname); + } + + if (ntups > 0) + appendPQExpBufferStr(q, ";\n"); + + PQclear(res); + + appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s;\n", + fmtQualifiedDumpable(cfginfo)); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &cfginfo->dobj, + "TEXT SEARCH CONFIGURATION", qcfgname, + cfginfo->dobj.namespace->dobj.name); + + if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = cfginfo->dobj.name, + .namespace = cfginfo->dobj.namespace->dobj.name, + .owner = cfginfo->rolname, + .description = "TEXT SEARCH CONFIGURATION", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Configuration Comments */ + if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "TEXT SEARCH CONFIGURATION", qcfgname, + cfginfo->dobj.namespace->dobj.name, cfginfo->rolname, + cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qcfgname); +} + +/* + * dumpForeignDataWrapper + * write out a single foreign-data wrapper definition + */ +static void +dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + char *qfdwname; + + /* Skip if not to be dumped */ + if (!fdwinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qfdwname = pg_strdup(fmtId(fdwinfo->dobj.name)); + + appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s", + qfdwname); + + if (strcmp(fdwinfo->fdwhandler, "-") != 0) + appendPQExpBuffer(q, " HANDLER %s", fdwinfo->fdwhandler); + + if (strcmp(fdwinfo->fdwvalidator, "-") != 0) + appendPQExpBuffer(q, " VALIDATOR %s", fdwinfo->fdwvalidator); + + if (strlen(fdwinfo->fdwoptions) > 0) + appendPQExpBuffer(q, " OPTIONS (\n %s\n)", fdwinfo->fdwoptions); + + appendPQExpBufferStr(q, ";\n"); + + appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n", + qfdwname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &fdwinfo->dobj, + "FOREIGN DATA WRAPPER", qfdwname, + NULL); + + if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = fdwinfo->dobj.name, + .owner = fdwinfo->rolname, + .description = "FOREIGN DATA WRAPPER", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Foreign Data Wrapper Comments */ + if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "FOREIGN DATA WRAPPER", qfdwname, + NULL, fdwinfo->rolname, + fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId); + + /* Handle the ACL */ + if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, fdwinfo->dobj.dumpId, InvalidDumpId, + "FOREIGN DATA WRAPPER", qfdwname, NULL, + NULL, fdwinfo->rolname, + fdwinfo->fdwacl, fdwinfo->rfdwacl, + fdwinfo->initfdwacl, fdwinfo->initrfdwacl); + + free(qfdwname); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); +} + +/* + * dumpForeignServer + * write out a foreign server definition + */ +static void +dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer query; + PGresult *res; + char *qsrvname; + char *fdwname; + + /* Skip if not to be dumped */ + if (!srvinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qsrvname = pg_strdup(fmtId(srvinfo->dobj.name)); + + /* look up the foreign-data wrapper */ + appendPQExpBuffer(query, "SELECT fdwname " + "FROM pg_foreign_data_wrapper w " + "WHERE w.oid = '%u'", + srvinfo->srvfdw); + res = ExecuteSqlQueryForSingleRow(fout, query->data); + fdwname = PQgetvalue(res, 0, 0); + + appendPQExpBuffer(q, "CREATE SERVER %s", qsrvname); + if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0) + { + appendPQExpBufferStr(q, " TYPE "); + appendStringLiteralAH(q, srvinfo->srvtype, fout); + } + if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0) + { + appendPQExpBufferStr(q, " VERSION "); + appendStringLiteralAH(q, srvinfo->srvversion, fout); + } + + appendPQExpBufferStr(q, " FOREIGN DATA WRAPPER "); + appendPQExpBufferStr(q, fmtId(fdwname)); + + if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0) + appendPQExpBuffer(q, " OPTIONS (\n %s\n)", srvinfo->srvoptions); + + appendPQExpBufferStr(q, ";\n"); + + appendPQExpBuffer(delq, "DROP SERVER %s;\n", + qsrvname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &srvinfo->dobj, + "SERVER", qsrvname, NULL); + + if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = srvinfo->dobj.name, + .owner = srvinfo->rolname, + .description = "SERVER", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Foreign Server Comments */ + if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "SERVER", qsrvname, + NULL, srvinfo->rolname, + srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId); + + /* Handle the ACL */ + if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL) + dumpACL(fout, srvinfo->dobj.dumpId, InvalidDumpId, + "FOREIGN SERVER", qsrvname, NULL, + NULL, srvinfo->rolname, + srvinfo->srvacl, srvinfo->rsrvacl, + srvinfo->initsrvacl, srvinfo->initrsrvacl); + + /* Dump user mappings */ + if (srvinfo->dobj.dump & DUMP_COMPONENT_USERMAP) + dumpUserMappings(fout, + srvinfo->dobj.name, NULL, + srvinfo->rolname, + srvinfo->dobj.catId, srvinfo->dobj.dumpId); + + free(qsrvname); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); +} + +/* + * dumpUserMappings + * + * This routine is used to dump any user mappings associated with the + * server handed to this routine. Should be called after ArchiveEntry() + * for the server. + */ +static void +dumpUserMappings(Archive *fout, + const char *servername, const char *namespace, + const char *owner, + CatalogId catalogId, DumpId dumpId) +{ + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer query; + PQExpBuffer tag; + PGresult *res; + int ntups; + int i_usename; + int i_umoptions; + int i; + + q = createPQExpBuffer(); + tag = createPQExpBuffer(); + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + /* + * We read from the publicly accessible view pg_user_mappings, so as not + * to fail if run by a non-superuser. Note that the view will show + * umoptions as null if the user hasn't got privileges for the associated + * server; this means that pg_dump will dump such a mapping, but with no + * OPTIONS clause. A possible alternative is to skip such mappings + * altogether, but it's not clear that that's an improvement. + */ + appendPQExpBuffer(query, + "SELECT usename, " + "array_to_string(ARRAY(" + "SELECT quote_ident(option_name) || ' ' || " + "quote_literal(option_value) " + "FROM pg_options_to_table(umoptions) " + "ORDER BY option_name" + "), E',\n ') AS umoptions " + "FROM pg_user_mappings " + "WHERE srvid = '%u' " + "ORDER BY usename", + catalogId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + i_usename = PQfnumber(res, "usename"); + i_umoptions = PQfnumber(res, "umoptions"); + + for (i = 0; i < ntups; i++) + { + char *usename; + char *umoptions; + + usename = PQgetvalue(res, i, i_usename); + umoptions = PQgetvalue(res, i, i_umoptions); + + resetPQExpBuffer(q); + appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(usename)); + appendPQExpBuffer(q, " SERVER %s", fmtId(servername)); + + if (umoptions && strlen(umoptions) > 0) + appendPQExpBuffer(q, " OPTIONS (\n %s\n)", umoptions); + + appendPQExpBufferStr(q, ";\n"); + + resetPQExpBuffer(delq); + appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s", fmtId(usename)); + appendPQExpBuffer(delq, " SERVER %s;\n", fmtId(servername)); + + resetPQExpBuffer(tag); + appendPQExpBuffer(tag, "USER MAPPING %s SERVER %s", + usename, servername); + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tag->data, + .namespace = namespace, + .owner = owner, + .description = "USER MAPPING", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(tag); + destroyPQExpBuffer(q); +} + +/* + * Write out default privileges information + */ +static void +dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer tag; + const char *type; + + /* Skip if not to be dumped */ + if (!daclinfo->dobj.dump || dopt->dataOnly || dopt->aclsSkip) + return; + + q = createPQExpBuffer(); + tag = createPQExpBuffer(); + + switch (daclinfo->defaclobjtype) + { + case DEFACLOBJ_RELATION: + type = "TABLES"; + break; + case DEFACLOBJ_SEQUENCE: + type = "SEQUENCES"; + break; + case DEFACLOBJ_FUNCTION: + type = "FUNCTIONS"; + break; + case DEFACLOBJ_TYPE: + type = "TYPES"; + break; + case DEFACLOBJ_NAMESPACE: + type = "SCHEMAS"; + break; + default: + /* shouldn't get here */ + fatal("unrecognized object type in default privileges: %d", + (int) daclinfo->defaclobjtype); + type = ""; /* keep compiler quiet */ + } + + appendPQExpBuffer(tag, "DEFAULT PRIVILEGES FOR %s", type); + + /* build the actual command(s) for this tuple */ + if (!buildDefaultACLCommands(type, + daclinfo->dobj.namespace != NULL ? + daclinfo->dobj.namespace->dobj.name : NULL, + daclinfo->defaclacl, + daclinfo->rdefaclacl, + daclinfo->initdefaclacl, + daclinfo->initrdefaclacl, + daclinfo->defaclrole, + fout->remoteVersion, + q)) + fatal("could not parse default ACL list (%s)", + daclinfo->defaclacl); + + if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL) + ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag->data, + .namespace = daclinfo->dobj.namespace ? + daclinfo->dobj.namespace->dobj.name : NULL, + .owner = daclinfo->defaclrole, + .description = "DEFAULT ACL", + .section = SECTION_POST_DATA, + .createStmt = q->data)); + + destroyPQExpBuffer(tag); + destroyPQExpBuffer(q); +} + +/*---------- + * Write out grant/revoke information + * + * 'objDumpId' is the dump ID of the underlying object. + * 'altDumpId' can be a second dumpId that the ACL entry must also depend on, + * or InvalidDumpId if there is no need for a second dependency. + * 'type' must be one of + * TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE, + * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT. + * 'name' is the formatted name of the object. Must be quoted etc. already. + * 'subname' is the formatted name of the sub-object, if any. Must be quoted. + * (Currently we assume that subname is only provided for table columns.) + * 'nspname' is the namespace the object is in (NULL if none). + * 'owner' is the owner, NULL if there is no owner (for languages). + * 'acls' contains the ACL string of the object from the appropriate system + * catalog field; it will be passed to buildACLCommands for building the + * appropriate GRANT commands. + * 'racls' contains the ACL string of any initial-but-now-revoked ACLs of the + * object; it will be passed to buildACLCommands for building the + * appropriate REVOKE commands. + * 'initacls' In binary-upgrade mode, ACL string of the object's initial + * privileges, to be recorded into pg_init_privs + * 'initracls' In binary-upgrade mode, ACL string of the object's + * revoked-from-default privileges, to be recorded into pg_init_privs + * + * NB: initacls/initracls are needed because extensions can set privileges on + * an object during the extension's script file and we record those into + * pg_init_privs as that object's initial privileges. + * + * Returns the dump ID assigned to the ACL TocEntry, or InvalidDumpId if + * no ACL entry was created. + *---------- + */ +static DumpId +dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId, + const char *type, const char *name, const char *subname, + const char *nspname, const char *owner, + const char *acls, const char *racls, + const char *initacls, const char *initracls) +{ + DumpId aclDumpId = InvalidDumpId; + DumpOptions *dopt = fout->dopt; + PQExpBuffer sql; + + /* Do nothing if ACL dump is not enabled */ + if (dopt->aclsSkip) + return InvalidDumpId; + + /* --data-only skips ACLs *except* BLOB ACLs */ + if (dopt->dataOnly && strcmp(type, "LARGE OBJECT") != 0) + return InvalidDumpId; + + sql = createPQExpBuffer(); + + /* + * Check to see if this object has had any initial ACLs included for it. + * If so, we are in binary upgrade mode and these are the ACLs to turn + * into GRANT and REVOKE statements to set and record the initial + * privileges for an extension object. Let the backend know that these + * are to be recorded by calling binary_upgrade_set_record_init_privs() + * before and after. + */ + if (strlen(initacls) != 0 || strlen(initracls) != 0) + { + appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n"); + if (!buildACLCommands(name, subname, nspname, type, + initacls, initracls, owner, + "", fout->remoteVersion, sql)) + fatal("could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)", + initacls, initracls, name, type); + appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n"); + } + + if (!buildACLCommands(name, subname, nspname, type, + acls, racls, owner, + "", fout->remoteVersion, sql)) + fatal("could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)", + acls, racls, name, type); + + if (sql->len > 0) + { + PQExpBuffer tag = createPQExpBuffer(); + DumpId aclDeps[2]; + int nDeps = 0; + + if (subname) + appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname); + else + appendPQExpBuffer(tag, "%s %s", type, name); + + aclDeps[nDeps++] = objDumpId; + if (altDumpId != InvalidDumpId) + aclDeps[nDeps++] = altDumpId; + + aclDumpId = createDumpId(); + + ArchiveEntry(fout, nilCatalogId, aclDumpId, + ARCHIVE_OPTS(.tag = tag->data, + .namespace = nspname, + .owner = owner, + .description = "ACL", + .section = SECTION_NONE, + .createStmt = sql->data, + .deps = aclDeps, + .nDeps = nDeps)); + + destroyPQExpBuffer(tag); + } + + destroyPQExpBuffer(sql); + + return aclDumpId; +} + +/* + * dumpSecLabel + * + * This routine is used to dump any security labels associated with the + * object handed to this routine. The routine takes the object type + * and object name (ready to print, except for schema decoration), plus + * the namespace and owner of the object (for labeling the ArchiveEntry), + * plus catalog ID and subid which are the lookup key for pg_seclabel, + * plus the dump ID for the object (for setting a dependency). + * If a matching pg_seclabel entry is found, it is dumped. + * + * Note: although this routine takes a dumpId for dependency purposes, + * that purpose is just to mark the dependency in the emitted dump file + * for possible future use by pg_restore. We do NOT use it for determining + * ordering of the label in the dump file, because this routine is called + * after dependency sorting occurs. This routine should be called just after + * calling ArchiveEntry() for the specified object. + */ +static void +dumpSecLabel(Archive *fout, const char *type, const char *name, + const char *namespace, const char *owner, + CatalogId catalogId, int subid, DumpId dumpId) +{ + DumpOptions *dopt = fout->dopt; + SecLabelItem *labels; + int nlabels; + int i; + PQExpBuffer query; + + /* do nothing, if --no-security-labels is supplied */ + if (dopt->no_security_labels) + return; + + /* Security labels are schema not data ... except blob labels are data */ + if (strcmp(type, "LARGE OBJECT") != 0) + { + if (dopt->dataOnly) + return; + } + else + { + /* We do dump blob security labels in binary-upgrade mode */ + if (dopt->schemaOnly && !dopt->binary_upgrade) + return; + } + + /* Search for security labels associated with catalogId, using table */ + nlabels = findSecLabels(fout, catalogId.tableoid, catalogId.oid, &labels); + + query = createPQExpBuffer(); + + for (i = 0; i < nlabels; i++) + { + /* + * Ignore label entries for which the subid doesn't match. + */ + if (labels[i].objsubid != subid) + continue; + + appendPQExpBuffer(query, + "SECURITY LABEL FOR %s ON %s ", + fmtId(labels[i].provider), type); + if (namespace && *namespace) + appendPQExpBuffer(query, "%s.", fmtId(namespace)); + appendPQExpBuffer(query, "%s IS ", name); + appendStringLiteralAH(query, labels[i].label, fout); + appendPQExpBufferStr(query, ";\n"); + } + + if (query->len > 0) + { + PQExpBuffer tag = createPQExpBuffer(); + + appendPQExpBuffer(tag, "%s %s", type, name); + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tag->data, + .namespace = namespace, + .owner = owner, + .description = "SECURITY LABEL", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &dumpId, + .nDeps = 1)); + destroyPQExpBuffer(tag); + } + + destroyPQExpBuffer(query); +} + +/* + * dumpTableSecLabel + * + * As above, but dump security label for both the specified table (or view) + * and its columns. + */ +static void +dumpTableSecLabel(Archive *fout, const TableInfo *tbinfo, const char *reltypename) +{ + DumpOptions *dopt = fout->dopt; + SecLabelItem *labels; + int nlabels; + int i; + PQExpBuffer query; + PQExpBuffer target; + + /* do nothing, if --no-security-labels is supplied */ + if (dopt->no_security_labels) + return; + + /* SecLabel are SCHEMA not data */ + if (dopt->dataOnly) + return; + + /* Search for comments associated with relation, using table */ + nlabels = findSecLabels(fout, + tbinfo->dobj.catId.tableoid, + tbinfo->dobj.catId.oid, + &labels); + + /* If security labels exist, build SECURITY LABEL statements */ + if (nlabels <= 0) + return; + + query = createPQExpBuffer(); + target = createPQExpBuffer(); + + for (i = 0; i < nlabels; i++) + { + const char *colname; + const char *provider = labels[i].provider; + const char *label = labels[i].label; + int objsubid = labels[i].objsubid; + + resetPQExpBuffer(target); + if (objsubid == 0) + { + appendPQExpBuffer(target, "%s %s", reltypename, + fmtQualifiedDumpable(tbinfo)); + } + else + { + colname = getAttrName(objsubid, tbinfo); + /* first fmtXXX result must be consumed before calling again */ + appendPQExpBuffer(target, "COLUMN %s", + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(target, ".%s", fmtId(colname)); + } + appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ", + fmtId(provider), target->data); + appendStringLiteralAH(query, label, fout); + appendPQExpBufferStr(query, ";\n"); + } + if (query->len > 0) + { + resetPQExpBuffer(target); + appendPQExpBuffer(target, "%s %s", reltypename, + fmtId(tbinfo->dobj.name)); + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = target->data, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "SECURITY LABEL", + .section = SECTION_NONE, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + } + destroyPQExpBuffer(query); + destroyPQExpBuffer(target); +} + +/* + * findSecLabels + * + * Find the security label(s), if any, associated with the given object. + * All the objsubid values associated with the given classoid/objoid are + * found with one search. + */ +static int +findSecLabels(Archive *fout, Oid classoid, Oid objoid, SecLabelItem **items) +{ + /* static storage for table of security labels */ + static SecLabelItem *labels = NULL; + static int nlabels = -1; + + SecLabelItem *middle = NULL; + SecLabelItem *low; + SecLabelItem *high; + int nmatch; + + /* Get security labels if we didn't already */ + if (nlabels < 0) + nlabels = collectSecLabels(fout, &labels); + + if (nlabels <= 0) /* no labels, so no match is possible */ + { + *items = NULL; + return 0; + } + + /* + * Do binary search to find some item matching the object. + */ + low = &labels[0]; + high = &labels[nlabels - 1]; + while (low <= high) + { + middle = low + (high - low) / 2; + + if (classoid < middle->classoid) + high = middle - 1; + else if (classoid > middle->classoid) + low = middle + 1; + else if (objoid < middle->objoid) + high = middle - 1; + else if (objoid > middle->objoid) + low = middle + 1; + else + break; /* found a match */ + } + + if (low > high) /* no matches */ + { + *items = NULL; + return 0; + } + + /* + * Now determine how many items match the object. The search loop + * invariant still holds: only items between low and high inclusive could + * match. + */ + nmatch = 1; + while (middle > low) + { + if (classoid != middle[-1].classoid || + objoid != middle[-1].objoid) + break; + middle--; + nmatch++; + } + + *items = middle; + + middle += nmatch; + while (middle <= high) + { + if (classoid != middle->classoid || + objoid != middle->objoid) + break; + middle++; + nmatch++; + } + + return nmatch; +} + +/* + * collectSecLabels + * + * Construct a table of all security labels available for database objects. + * It's much faster to pull them all at once. + * + * The table is sorted by classoid/objid/objsubid for speed in lookup. + */ +static int +collectSecLabels(Archive *fout, SecLabelItem **items) +{ + PGresult *res; + PQExpBuffer query; + int i_label; + int i_provider; + int i_classoid; + int i_objoid; + int i_objsubid; + int ntups; + int i; + SecLabelItem *labels; + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, + "SELECT label, provider, classoid, objoid, objsubid " + "FROM pg_catalog.pg_seclabel " + "ORDER BY classoid, objoid, objsubid"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + /* Construct lookup table containing OIDs in numeric form */ + i_label = PQfnumber(res, "label"); + i_provider = PQfnumber(res, "provider"); + i_classoid = PQfnumber(res, "classoid"); + i_objoid = PQfnumber(res, "objoid"); + i_objsubid = PQfnumber(res, "objsubid"); + + ntups = PQntuples(res); + + labels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem)); + + for (i = 0; i < ntups; i++) + { + labels[i].label = PQgetvalue(res, i, i_label); + labels[i].provider = PQgetvalue(res, i, i_provider); + labels[i].classoid = atooid(PQgetvalue(res, i, i_classoid)); + labels[i].objoid = atooid(PQgetvalue(res, i, i_objoid)); + labels[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid)); + } + + /* Do NOT free the PGresult since we are keeping pointers into it */ + destroyPQExpBuffer(query); + + *items = labels; + return ntups; +} + +/* + * dumpTable + * write out to fout the declarations (not data) of a user-defined table + */ +static void +dumpTable(Archive *fout, const TableInfo *tbinfo) +{ + DumpOptions *dopt = fout->dopt; + DumpId tableAclDumpId = InvalidDumpId; + char *namecopy; + + /* + * noop if we are not dumping anything about this table, or if we are + * doing a data-only dump + */ + if (!tbinfo->dobj.dump || dopt->dataOnly) + return; + + if (tbinfo->relkind == RELKIND_SEQUENCE) + dumpSequence(fout, tbinfo); + else + dumpTableSchema(fout, tbinfo); + + /* Handle the ACL here */ + namecopy = pg_strdup(fmtId(tbinfo->dobj.name)); + if (tbinfo->dobj.dump & DUMP_COMPONENT_ACL) + { + const char *objtype = + (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE"; + + tableAclDumpId = + dumpACL(fout, tbinfo->dobj.dumpId, InvalidDumpId, + objtype, namecopy, NULL, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + tbinfo->relacl, tbinfo->rrelacl, + tbinfo->initrelacl, tbinfo->initrrelacl); + } + + /* + * Handle column ACLs, if any. Note: we pull these with a separate query + * rather than trying to fetch them during getTableAttrs, so that we won't + * miss ACLs on system columns. + */ + if (fout->remoteVersion >= 80400 && tbinfo->dobj.dump & DUMP_COMPONENT_ACL) + { + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + int i; + + if (fout->remoteVersion >= 90600) + { + PQExpBuffer acl_subquery = createPQExpBuffer(); + PQExpBuffer racl_subquery = createPQExpBuffer(); + PQExpBuffer initacl_subquery = createPQExpBuffer(); + PQExpBuffer initracl_subquery = createPQExpBuffer(); + + buildACLQueries(acl_subquery, racl_subquery, initacl_subquery, + initracl_subquery, "at.attacl", "c.relowner", "'c'", + dopt->binary_upgrade); + + appendPQExpBuffer(query, + "SELECT at.attname, " + "%s AS attacl, " + "%s AS rattacl, " + "%s AS initattacl, " + "%s AS initrattacl " + "FROM pg_catalog.pg_attribute at " + "JOIN pg_catalog.pg_class c ON (at.attrelid = c.oid) " + "LEFT JOIN pg_catalog.pg_init_privs pip ON " + "(at.attrelid = pip.objoid " + "AND pip.classoid = 'pg_catalog.pg_class'::pg_catalog.regclass " + "AND at.attnum = pip.objsubid) " + "WHERE at.attrelid = '%u'::pg_catalog.oid AND " + "NOT at.attisdropped " + "AND (" + "%s IS NOT NULL OR " + "%s IS NOT NULL OR " + "%s IS NOT NULL OR " + "%s IS NOT NULL)" + "ORDER BY at.attnum", + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data, + tbinfo->dobj.catId.oid, + acl_subquery->data, + racl_subquery->data, + initacl_subquery->data, + initracl_subquery->data); + + destroyPQExpBuffer(acl_subquery); + destroyPQExpBuffer(racl_subquery); + destroyPQExpBuffer(initacl_subquery); + destroyPQExpBuffer(initracl_subquery); + } + else + { + appendPQExpBuffer(query, + "SELECT attname, attacl, NULL as rattacl, " + "NULL AS initattacl, NULL AS initrattacl " + "FROM pg_catalog.pg_attribute " + "WHERE attrelid = '%u'::pg_catalog.oid AND NOT attisdropped " + "AND attacl IS NOT NULL " + "ORDER BY attnum", + tbinfo->dobj.catId.oid); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + for (i = 0; i < PQntuples(res); i++) + { + char *attname = PQgetvalue(res, i, 0); + char *attacl = PQgetvalue(res, i, 1); + char *rattacl = PQgetvalue(res, i, 2); + char *initattacl = PQgetvalue(res, i, 3); + char *initrattacl = PQgetvalue(res, i, 4); + char *attnamecopy; + + attnamecopy = pg_strdup(fmtId(attname)); + + /* + * Column's GRANT type is always TABLE. Each column ACL depends + * on the table-level ACL, since we can restore column ACLs in + * parallel but the table-level ACL has to be done first. + */ + dumpACL(fout, tbinfo->dobj.dumpId, tableAclDumpId, + "TABLE", namecopy, attnamecopy, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + attacl, rattacl, initattacl, initrattacl); + free(attnamecopy); + } + PQclear(res); + destroyPQExpBuffer(query); + } + + free(namecopy); +} + +/* + * Create the AS clause for a view or materialized view. The semicolon is + * stripped because a materialized view must add a WITH NO DATA clause. + * + * This returns a new buffer which must be freed by the caller. + */ +static PQExpBuffer +createViewAsClause(Archive *fout, const TableInfo *tbinfo) +{ + PQExpBuffer query = createPQExpBuffer(); + PQExpBuffer result = createPQExpBuffer(); + PGresult *res; + int len; + + /* Fetch the view definition */ + appendPQExpBuffer(query, + "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef", + tbinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + if (PQntuples(res) != 1) + { + if (PQntuples(res) < 1) + fatal("query to obtain definition of view \"%s\" returned no data", + tbinfo->dobj.name); + else + fatal("query to obtain definition of view \"%s\" returned more than one definition", + tbinfo->dobj.name); + } + + len = PQgetlength(res, 0, 0); + + if (len == 0) + fatal("definition of view \"%s\" appears to be empty (length zero)", + tbinfo->dobj.name); + + /* Strip off the trailing semicolon so that other things may follow. */ + Assert(PQgetvalue(res, 0, 0)[len - 1] == ';'); + appendBinaryPQExpBuffer(result, PQgetvalue(res, 0, 0), len - 1); + + PQclear(res); + destroyPQExpBuffer(query); + + return result; +} + +/* + * Create a dummy AS clause for a view. This is used when the real view + * definition has to be postponed because of circular dependencies. + * We must duplicate the view's external properties -- column names and types + * (including collation) -- so that it works for subsequent references. + * + * This returns a new buffer which must be freed by the caller. + */ +static PQExpBuffer +createDummyViewAsClause(Archive *fout, const TableInfo *tbinfo) +{ + PQExpBuffer result = createPQExpBuffer(); + int j; + + appendPQExpBufferStr(result, "SELECT"); + + for (j = 0; j < tbinfo->numatts; j++) + { + if (j > 0) + appendPQExpBufferChar(result, ','); + appendPQExpBufferStr(result, "\n "); + + appendPQExpBuffer(result, "NULL::%s", tbinfo->atttypnames[j]); + + /* + * Must add collation if not default for the type, because CREATE OR + * REPLACE VIEW won't change it + */ + if (OidIsValid(tbinfo->attcollation[j])) + { + CollInfo *coll; + + coll = findCollationByOid(tbinfo->attcollation[j]); + if (coll) + appendPQExpBuffer(result, " COLLATE %s", + fmtQualifiedDumpable(coll)); + } + + appendPQExpBuffer(result, " AS %s", fmtId(tbinfo->attnames[j])); + } + + return result; +} + +/* + * dumpTableSchema + * write the declaration (not data) of one user-defined table or view + */ +static void +dumpTableSchema(Archive *fout, const TableInfo *tbinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer delq = createPQExpBuffer(); + char *qrelname; + char *qualrelname; + int numParents; + TableInfo **parents; + int actual_atts; /* number of attrs in this CREATE statement */ + const char *reltypename; + char *storage; + int j, + k; + + /* We had better have loaded per-column details about this table */ + Assert(tbinfo->interesting); + + qrelname = pg_strdup(fmtId(tbinfo->dobj.name)); + qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo)); + + if (tbinfo->hasoids) + pg_log_warning("WITH OIDS is not supported anymore (table \"%s\")", + qrelname); + + if (dopt->binary_upgrade) + binary_upgrade_set_type_oids_by_rel_oid(fout, q, + tbinfo->dobj.catId.oid); + + /* Is it a table or a view? */ + if (tbinfo->relkind == RELKIND_VIEW) + { + PQExpBuffer result; + + /* + * Note: keep this code in sync with the is_view case in dumpRule() + */ + + reltypename = "VIEW"; + + appendPQExpBuffer(delq, "DROP VIEW %s;\n", qualrelname); + + if (dopt->binary_upgrade) + binary_upgrade_set_pg_class_oids(fout, q, + tbinfo->dobj.catId.oid, false); + + appendPQExpBuffer(q, "CREATE VIEW %s", qualrelname); + + if (tbinfo->dummy_view) + result = createDummyViewAsClause(fout, tbinfo); + else + { + if (nonemptyReloptions(tbinfo->reloptions)) + { + appendPQExpBufferStr(q, " WITH ("); + appendReloptionsArrayAH(q, tbinfo->reloptions, "", fout); + appendPQExpBufferChar(q, ')'); + } + result = createViewAsClause(fout, tbinfo); + } + appendPQExpBuffer(q, " AS\n%s", result->data); + destroyPQExpBuffer(result); + + if (tbinfo->checkoption != NULL && !tbinfo->dummy_view) + appendPQExpBuffer(q, "\n WITH %s CHECK OPTION", tbinfo->checkoption); + appendPQExpBufferStr(q, ";\n"); + } + else + { + char *ftoptions = NULL; + char *srvname = NULL; + char *foreign = ""; + + switch (tbinfo->relkind) + { + case RELKIND_FOREIGN_TABLE: + { + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + int i_srvname; + int i_ftoptions; + + reltypename = "FOREIGN TABLE"; + + /* retrieve name of foreign server and generic options */ + appendPQExpBuffer(query, + "SELECT fs.srvname, " + "pg_catalog.array_to_string(ARRAY(" + "SELECT pg_catalog.quote_ident(option_name) || " + "' ' || pg_catalog.quote_literal(option_value) " + "FROM pg_catalog.pg_options_to_table(ftoptions) " + "ORDER BY option_name" + "), E',\n ') AS ftoptions " + "FROM pg_catalog.pg_foreign_table ft " + "JOIN pg_catalog.pg_foreign_server fs " + "ON (fs.oid = ft.ftserver) " + "WHERE ft.ftrelid = '%u'", + tbinfo->dobj.catId.oid); + res = ExecuteSqlQueryForSingleRow(fout, query->data); + i_srvname = PQfnumber(res, "srvname"); + i_ftoptions = PQfnumber(res, "ftoptions"); + srvname = pg_strdup(PQgetvalue(res, 0, i_srvname)); + ftoptions = pg_strdup(PQgetvalue(res, 0, i_ftoptions)); + PQclear(res); + destroyPQExpBuffer(query); + + foreign = "FOREIGN "; + break; + } + case RELKIND_MATVIEW: + reltypename = "MATERIALIZED VIEW"; + break; + default: + reltypename = "TABLE"; + } + + numParents = tbinfo->numParents; + parents = tbinfo->parents; + + appendPQExpBuffer(delq, "DROP %s %s;\n", reltypename, qualrelname); + + if (dopt->binary_upgrade) + binary_upgrade_set_pg_class_oids(fout, q, + tbinfo->dobj.catId.oid, false); + + appendPQExpBuffer(q, "CREATE %s%s %s", + tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? + "UNLOGGED " : "", + reltypename, + qualrelname); + + /* + * Attach to type, if reloftype; except in case of a binary upgrade, + * we dump the table normally and attach it to the type afterward. + */ + if (tbinfo->reloftype && !dopt->binary_upgrade) + appendPQExpBuffer(q, " OF %s", tbinfo->reloftype); + + if (tbinfo->relkind != RELKIND_MATVIEW) + { + /* Dump the attributes */ + actual_atts = 0; + for (j = 0; j < tbinfo->numatts; j++) + { + /* + * Normally, dump if it's locally defined in this table, and + * not dropped. But for binary upgrade, we'll dump all the + * columns, and then fix up the dropped and nonlocal cases + * below. + */ + if (shouldPrintColumn(dopt, tbinfo, j)) + { + bool print_default; + bool print_notnull; + + /* + * Default value --- suppress if to be printed separately. + */ + print_default = (tbinfo->attrdefs[j] != NULL && + !tbinfo->attrdefs[j]->separate); + + /* + * Not Null constraint --- suppress if inherited, except + * if partition, or in binary-upgrade case where that + * won't work. + */ + print_notnull = (tbinfo->notnull[j] && + (!tbinfo->inhNotNull[j] || + tbinfo->ispartition || dopt->binary_upgrade)); + + /* + * Skip column if fully defined by reloftype, except in + * binary upgrade + */ + if (tbinfo->reloftype && !print_default && !print_notnull && + !dopt->binary_upgrade) + continue; + + /* Format properly if not first attr */ + if (actual_atts == 0) + appendPQExpBufferStr(q, " ("); + else + appendPQExpBufferChar(q, ','); + appendPQExpBufferStr(q, "\n "); + actual_atts++; + + /* Attribute name */ + appendPQExpBufferStr(q, fmtId(tbinfo->attnames[j])); + + if (tbinfo->attisdropped[j]) + { + /* + * ALTER TABLE DROP COLUMN clears + * pg_attribute.atttypid, so we will not have gotten a + * valid type name; insert INTEGER as a stopgap. We'll + * clean things up later. + */ + appendPQExpBufferStr(q, " INTEGER /* dummy */"); + /* and skip to the next column */ + continue; + } + + /* + * Attribute type; print it except when creating a typed + * table ('OF type_name'), but in binary-upgrade mode, + * print it in that case too. + */ + if (dopt->binary_upgrade || !tbinfo->reloftype) + { + appendPQExpBuffer(q, " %s", + tbinfo->atttypnames[j]); + } + + if (print_default) + { + if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_STORED) + appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s) STORED", + tbinfo->attrdefs[j]->adef_expr); + else + appendPQExpBuffer(q, " DEFAULT %s", + tbinfo->attrdefs[j]->adef_expr); + } + + + if (print_notnull) + appendPQExpBufferStr(q, " NOT NULL"); + + /* Add collation if not default for the type */ + if (OidIsValid(tbinfo->attcollation[j])) + { + CollInfo *coll; + + coll = findCollationByOid(tbinfo->attcollation[j]); + if (coll) + appendPQExpBuffer(q, " COLLATE %s", + fmtQualifiedDumpable(coll)); + } + } + } + + /* + * Add non-inherited CHECK constraints, if any. + * + * For partitions, we need to include check constraints even if + * they're not defined locally, because the ALTER TABLE ATTACH + * PARTITION that we'll emit later expects the constraint to be + * there. (No need to fix conislocal: ATTACH PARTITION does that) + */ + for (j = 0; j < tbinfo->ncheck; j++) + { + ConstraintInfo *constr = &(tbinfo->checkexprs[j]); + + if (constr->separate || + (!constr->conislocal && !tbinfo->ispartition)) + continue; + + if (actual_atts == 0) + appendPQExpBufferStr(q, " (\n "); + else + appendPQExpBufferStr(q, ",\n "); + + appendPQExpBuffer(q, "CONSTRAINT %s ", + fmtId(constr->dobj.name)); + appendPQExpBufferStr(q, constr->condef); + + actual_atts++; + } + + if (actual_atts) + appendPQExpBufferStr(q, "\n)"); + else if (!(tbinfo->reloftype && !dopt->binary_upgrade)) + { + /* + * No attributes? we must have a parenthesized attribute list, + * even though empty, when not using the OF TYPE syntax. + */ + appendPQExpBufferStr(q, " (\n)"); + } + + /* + * Emit the INHERITS clause (not for partitions), except in + * binary-upgrade mode. + */ + if (numParents > 0 && !tbinfo->ispartition && + !dopt->binary_upgrade) + { + appendPQExpBufferStr(q, "\nINHERITS ("); + for (k = 0; k < numParents; k++) + { + TableInfo *parentRel = parents[k]; + + if (k > 0) + appendPQExpBufferStr(q, ", "); + appendPQExpBufferStr(q, fmtQualifiedDumpable(parentRel)); + } + appendPQExpBufferChar(q, ')'); + } + + if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE) + appendPQExpBuffer(q, "\nPARTITION BY %s", tbinfo->partkeydef); + + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE) + appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname)); + } + + if (nonemptyReloptions(tbinfo->reloptions) || + nonemptyReloptions(tbinfo->toast_reloptions)) + { + bool addcomma = false; + + appendPQExpBufferStr(q, "\nWITH ("); + if (nonemptyReloptions(tbinfo->reloptions)) + { + addcomma = true; + appendReloptionsArrayAH(q, tbinfo->reloptions, "", fout); + } + if (nonemptyReloptions(tbinfo->toast_reloptions)) + { + if (addcomma) + appendPQExpBufferStr(q, ", "); + appendReloptionsArrayAH(q, tbinfo->toast_reloptions, "toast.", + fout); + } + appendPQExpBufferChar(q, ')'); + } + + /* Dump generic options if any */ + if (ftoptions && ftoptions[0]) + appendPQExpBuffer(q, "\nOPTIONS (\n %s\n)", ftoptions); + + /* + * For materialized views, create the AS clause just like a view. At + * this point, we always mark the view as not populated. + */ + if (tbinfo->relkind == RELKIND_MATVIEW) + { + PQExpBuffer result; + + result = createViewAsClause(fout, tbinfo); + appendPQExpBuffer(q, " AS\n%s\n WITH NO DATA;\n", + result->data); + destroyPQExpBuffer(result); + } + else + appendPQExpBufferStr(q, ";\n"); + + /* Materialized views can depend on extensions */ + if (tbinfo->relkind == RELKIND_MATVIEW) + append_depends_on_extension(fout, q, &tbinfo->dobj, + "pg_catalog.pg_class", + tbinfo->relkind == RELKIND_MATVIEW ? + "MATERIALIZED VIEW" : "INDEX", + qualrelname); + + /* + * in binary upgrade mode, update the catalog with any missing values + * that might be present. + */ + if (dopt->binary_upgrade) + { + for (j = 0; j < tbinfo->numatts; j++) + { + if (tbinfo->attmissingval[j][0] != '\0') + { + appendPQExpBufferStr(q, "\n-- set missing value.\n"); + appendPQExpBufferStr(q, + "SELECT pg_catalog.binary_upgrade_set_missing_value("); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass,"); + appendStringLiteralAH(q, tbinfo->attnames[j], fout); + appendPQExpBufferStr(q, ","); + appendStringLiteralAH(q, tbinfo->attmissingval[j], fout); + appendPQExpBufferStr(q, ");\n\n"); + } + } + } + + /* + * To create binary-compatible heap files, we have to ensure the same + * physical column order, including dropped columns, as in the + * original. Therefore, we create dropped columns above and drop them + * here, also updating their attlen/attalign values so that the + * dropped column can be skipped properly. (We do not bother with + * restoring the original attbyval setting.) Also, inheritance + * relationships are set up by doing ALTER TABLE INHERIT rather than + * using an INHERITS clause --- the latter would possibly mess up the + * column order. That also means we have to take care about setting + * attislocal correctly, plus fix up any inherited CHECK constraints. + * Analogously, we set up typed tables using ALTER TABLE / OF here. + * + * We process foreign and partitioned tables here, even though they + * lack heap storage, because they can participate in inheritance + * relationships and we want this stuff to be consistent across the + * inheritance tree. We can exclude indexes, toast tables, sequences + * and matviews, even though they have storage, because we don't + * support altering or dropping columns in them, nor can they be part + * of inheritance trees. + */ + if (dopt->binary_upgrade && + (tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_FOREIGN_TABLE || + tbinfo->relkind == RELKIND_PARTITIONED_TABLE)) + { + for (j = 0; j < tbinfo->numatts; j++) + { + if (tbinfo->attisdropped[j]) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate dropped column.\n"); + appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n" + "SET attlen = %d, " + "attalign = '%c', attbyval = false\n" + "WHERE attname = ", + tbinfo->attlen[j], + tbinfo->attalign[j]); + appendStringLiteralAH(q, tbinfo->attnames[j], fout); + appendPQExpBufferStr(q, "\n AND attrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + + if (tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_PARTITIONED_TABLE) + appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", + qualrelname); + else + appendPQExpBuffer(q, "ALTER FOREIGN TABLE ONLY %s ", + qualrelname); + appendPQExpBuffer(q, "DROP COLUMN %s;\n", + fmtId(tbinfo->attnames[j])); + } + else if (!tbinfo->attislocal[j]) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate inherited column.\n"); + appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_attribute\n" + "SET attislocal = false\n" + "WHERE attname = "); + appendStringLiteralAH(q, tbinfo->attnames[j], fout); + appendPQExpBufferStr(q, "\n AND attrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + } + } + + /* + * Add inherited CHECK constraints, if any. + * + * For partitions, they were already dumped, and conislocal + * doesn't need fixing. + */ + for (k = 0; k < tbinfo->ncheck; k++) + { + ConstraintInfo *constr = &(tbinfo->checkexprs[k]); + + if (constr->separate || constr->conislocal || tbinfo->ispartition) + continue; + + appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n"); + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ADD CONSTRAINT %s %s;\n", + foreign, qualrelname, + fmtId(constr->dobj.name), + constr->condef); + appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_constraint\n" + "SET conislocal = false\n" + "WHERE contype = 'c' AND conname = "); + appendStringLiteralAH(q, constr->dobj.name, fout); + appendPQExpBufferStr(q, "\n AND conrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + } + + if (numParents > 0 && !tbinfo->ispartition) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n"); + for (k = 0; k < numParents; k++) + { + TableInfo *parentRel = parents[k]; + + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s INHERIT %s;\n", foreign, + qualrelname, + fmtQualifiedDumpable(parentRel)); + } + } + + if (tbinfo->reloftype) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n"); + appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n", + qualrelname, + tbinfo->reloftype); + } + } + + /* + * In binary_upgrade mode, arrange to restore the old relfrozenxid and + * relminmxid of all vacuumable relations. (While vacuum.c processes + * TOAST tables semi-independently, here we see them only as children + * of other relations; so this "if" lacks RELKIND_TOASTVALUE, and the + * child toast table is handled below.) + */ + if (dopt->binary_upgrade && + (tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_MATVIEW)) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n"); + appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" + "WHERE oid = ", + tbinfo->frozenxid, tbinfo->minmxid); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + + if (tbinfo->toast_oid) + { + /* + * The toast table will have the same OID at restore, so we + * can safely target it by OID. + */ + appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n"); + appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" + "WHERE oid = '%u';\n", + tbinfo->toast_frozenxid, + tbinfo->toast_minmxid, tbinfo->toast_oid); + } + } + + /* + * In binary_upgrade mode, restore matviews' populated status by + * poking pg_class directly. This is pretty ugly, but we can't use + * REFRESH MATERIALIZED VIEW since it's possible that some underlying + * matview is not populated even though this matview is; in any case, + * we want to transfer the matview's heap storage, not run REFRESH. + */ + if (dopt->binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW && + tbinfo->relispopulated) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, mark materialized view as populated\n"); + appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n" + "SET relispopulated = 't'\n" + "WHERE oid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + } + + /* + * Dump additional per-column properties that we can't handle in the + * main CREATE TABLE command. + */ + for (j = 0; j < tbinfo->numatts; j++) + { + /* None of this applies to dropped columns */ + if (tbinfo->attisdropped[j]) + continue; + + /* + * If we didn't dump the column definition explicitly above, and + * it is NOT NULL and did not inherit that property from a parent, + * we have to mark it separately. + */ + if (!shouldPrintColumn(dopt, tbinfo, j) && + tbinfo->notnull[j] && !tbinfo->inhNotNull[j]) + appendPQExpBuffer(q, + "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET NOT NULL;\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j])); + + /* + * Dump per-column statistics information. We only issue an ALTER + * TABLE statement if the attstattarget entry for this column is + * non-negative (i.e. it's not the default value) + */ + if (tbinfo->attstattarget[j] >= 0) + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STATISTICS %d;\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j]), + tbinfo->attstattarget[j]); + + /* + * Dump per-column storage information. The statement is only + * dumped if the storage has been changed from the type's default. + */ + if (tbinfo->attstorage[j] != tbinfo->typstorage[j]) + { + switch (tbinfo->attstorage[j]) + { + case TYPSTORAGE_PLAIN: + storage = "PLAIN"; + break; + case TYPSTORAGE_EXTERNAL: + storage = "EXTERNAL"; + break; + case TYPSTORAGE_EXTENDED: + storage = "EXTENDED"; + break; + case TYPSTORAGE_MAIN: + storage = "MAIN"; + break; + default: + storage = NULL; + } + + /* + * Only dump the statement if it's a storage type we recognize + */ + if (storage != NULL) + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STORAGE %s;\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j]), + storage); + } + + /* + * Dump per-column compression, if it's been set. + */ + if (!dopt->no_toast_compression) + { + const char *cmname; + + switch (tbinfo->attcompression[j]) + { + case 'p': + cmname = "pglz"; + break; + case 'l': + cmname = "lz4"; + break; + default: + cmname = NULL; + break; + } + + if (cmname != NULL) + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET COMPRESSION %s;\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j]), + cmname); + } + + /* + * Dump per-column attributes. + */ + if (tbinfo->attoptions[j][0] != '\0') + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET (%s);\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[j]), + tbinfo->attoptions[j]); + + /* + * Dump per-column fdw options. + */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && + tbinfo->attfdwoptions[j][0] != '\0') + appendPQExpBuffer(q, + "ALTER FOREIGN TABLE %s ALTER COLUMN %s OPTIONS (\n" + " %s\n" + ");\n", + qualrelname, + fmtId(tbinfo->attnames[j]), + tbinfo->attfdwoptions[j]); + } /* end loop over columns */ + + if (ftoptions) + free(ftoptions); + if (srvname) + free(srvname); + } + + /* + * dump properties we only have ALTER TABLE syntax for + */ + if ((tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_PARTITIONED_TABLE || + tbinfo->relkind == RELKIND_MATVIEW) && + tbinfo->relreplident != REPLICA_IDENTITY_DEFAULT) + { + if (tbinfo->relreplident == REPLICA_IDENTITY_INDEX) + { + /* nothing to do, will be set when the index is dumped */ + } + else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING) + { + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n", + qualrelname); + } + else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL) + { + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n", + qualrelname); + } + } + + if (tbinfo->forcerowsec) + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s FORCE ROW LEVEL SECURITY;\n", + qualrelname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(q, &tbinfo->dobj, + reltypename, qrelname, + tbinfo->dobj.namespace->dobj.name); + + if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + { + char *tableam = NULL; + + if (tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_MATVIEW) + tableam = tbinfo->amname; + + ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .tablespace = (tbinfo->relkind == RELKIND_VIEW) ? + NULL : tbinfo->reltablespace, + .tableam = tableam, + .owner = tbinfo->rolname, + .description = reltypename, + .section = tbinfo->postponed_def ? + SECTION_POST_DATA : SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + + /* Dump Table Comments */ + if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpTableComment(fout, tbinfo, reltypename); + + /* Dump Table Security Labels */ + if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpTableSecLabel(fout, tbinfo, reltypename); + + /* Dump comments on inlined table constraints */ + for (j = 0; j < tbinfo->ncheck; j++) + { + ConstraintInfo *constr = &(tbinfo->checkexprs[j]); + + if (constr->separate || !constr->conislocal) + continue; + + if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpTableConstraintComment(fout, constr); + } + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qrelname); + free(qualrelname); +} + +/* + * dumpTableAttach + * write to fout the commands to attach a child partition + * + * Child partitions are always made by creating them separately + * and then using ATTACH PARTITION, rather than using + * CREATE TABLE ... PARTITION OF. This is important for preserving + * any possible discrepancy in column layout, to allow assigning the + * correct tablespace if different, and so that it's possible to restore + * a partition without restoring its parent. (You'll get an error from + * the ATTACH PARTITION command, but that can be ignored, or skipped + * using "pg_restore -L" if you prefer.) The last point motivates + * treating ATTACH PARTITION as a completely separate ArchiveEntry + * rather than emitting it within the child partition's ArchiveEntry. + */ +static void +dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + + if (dopt->dataOnly) + return; + + if (!(attachinfo->partitionTbl->dobj.dump & DUMP_COMPONENT_DEFINITION)) + return; + + q = createPQExpBuffer(); + + /* Perform ALTER TABLE on the parent */ + appendPQExpBuffer(q, + "ALTER TABLE ONLY %s ", + fmtQualifiedDumpable(attachinfo->parentTbl)); + appendPQExpBuffer(q, + "ATTACH PARTITION %s %s;\n", + fmtQualifiedDumpable(attachinfo->partitionTbl), + attachinfo->partitionTbl->partbound); + + /* + * There is no point in creating a drop query as the drop is done by table + * drop. (If you think to change this, see also _printTocEntry().) + * Although this object doesn't really have ownership as such, set the + * owner field anyway to ensure that the command is run by the correct + * role at restore time. + */ + ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = attachinfo->dobj.name, + .namespace = attachinfo->dobj.namespace->dobj.name, + .owner = attachinfo->partitionTbl->rolname, + .description = "TABLE ATTACH", + .section = SECTION_PRE_DATA, + .createStmt = q->data)); + + destroyPQExpBuffer(q); +} + +/* + * dumpAttrDef --- dump an attribute's default-value declaration + */ +static void +dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = adinfo->adtable; + int adnum = adinfo->adnum; + PQExpBuffer q; + PQExpBuffer delq; + char *qualrelname; + char *tag; + char *foreign; + + /* Skip if table definition not to be dumped */ + if (!tbinfo->dobj.dump || dopt->dataOnly) + return; + + /* Skip if not "separate"; it was dumped in the table's definition */ + if (!adinfo->separate) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo)); + + foreign = tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : ""; + + appendPQExpBuffer(q, + "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET DEFAULT %s;\n", + foreign, qualrelname, fmtId(tbinfo->attnames[adnum - 1]), + adinfo->adef_expr); + + appendPQExpBuffer(delq, "ALTER %sTABLE %s ALTER COLUMN %s DROP DEFAULT;\n", + foreign, qualrelname, + fmtId(tbinfo->attnames[adnum - 1])); + + tag = psprintf("%s %s", tbinfo->dobj.name, tbinfo->attnames[adnum - 1]); + + if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "DEFAULT", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + free(tag); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qualrelname); +} + +/* + * getAttrName: extract the correct name for an attribute + * + * The array tblInfo->attnames[] only provides names of user attributes; + * if a system attribute number is supplied, we have to fake it. + * We also do a little bit of bounds checking for safety's sake. + */ +static const char * +getAttrName(int attrnum, const TableInfo *tblInfo) +{ + if (attrnum > 0 && attrnum <= tblInfo->numatts) + return tblInfo->attnames[attrnum - 1]; + switch (attrnum) + { + case SelfItemPointerAttributeNumber: + return "ctid"; + case MinTransactionIdAttributeNumber: + return "xmin"; + case MinCommandIdAttributeNumber: + return "cmin"; + case MaxTransactionIdAttributeNumber: + return "xmax"; + case MaxCommandIdAttributeNumber: + return "cmax"; + case TableOidAttributeNumber: + return "tableoid"; + } + fatal("invalid column number %d for table \"%s\"", + attrnum, tblInfo->dobj.name); + return NULL; /* keep compiler quiet */ +} + +/* + * dumpIndex + * write out to fout a user-defined index + */ +static void +dumpIndex(Archive *fout, const IndxInfo *indxinfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = indxinfo->indextable; + bool is_constraint = (indxinfo->indexconstraint != 0); + PQExpBuffer q; + PQExpBuffer delq; + char *qindxname; + char *qqindxname; + + if (dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qindxname = pg_strdup(fmtId(indxinfo->dobj.name)); + qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo)); + + /* + * If there's an associated constraint, don't dump the index per se, but + * do dump any comment for it. (This is safe because dependency ordering + * will have ensured the constraint is emitted first.) Note that the + * emitted comment has to be shown as depending on the constraint, not the + * index, in such cases. + */ + if (!is_constraint) + { + char *indstatcols = indxinfo->indstatcols; + char *indstatvals = indxinfo->indstatvals; + char **indstatcolsarray = NULL; + char **indstatvalsarray = NULL; + int nstatcols = 0; + int nstatvals = 0; + + if (dopt->binary_upgrade) + binary_upgrade_set_pg_class_oids(fout, q, + indxinfo->dobj.catId.oid, true); + + /* Plain secondary index */ + appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef); + + /* + * Append ALTER TABLE commands as needed to set properties that we + * only have ALTER TABLE syntax for. Keep this in sync with the + * similar code in dumpConstraint! + */ + + /* If the index is clustered, we need to record that. */ + if (indxinfo->indisclustered) + { + appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " ON %s;\n", + qindxname); + } + + /* + * If the index has any statistics on some of its columns, generate + * the associated ALTER INDEX queries. + */ + if (strlen(indstatcols) != 0 || strlen(indstatvals) != 0) + { + int j; + + if (!parsePGArray(indstatcols, &indstatcolsarray, &nstatcols)) + fatal("could not parse index statistic columns"); + if (!parsePGArray(indstatvals, &indstatvalsarray, &nstatvals)) + fatal("could not parse index statistic values"); + if (nstatcols != nstatvals) + fatal("mismatched number of columns and values for index statistics"); + + for (j = 0; j < nstatcols; j++) + { + appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname); + + /* + * Note that this is a column number, so no quotes should be + * used. + */ + appendPQExpBuffer(q, "ALTER COLUMN %s ", + indstatcolsarray[j]); + appendPQExpBuffer(q, "SET STATISTICS %s;\n", + indstatvalsarray[j]); + } + } + + /* Indexes can depend on extensions */ + append_depends_on_extension(fout, q, &indxinfo->dobj, + "pg_catalog.pg_class", + "INDEX", qqindxname); + + /* If the index defines identity, we need to record that. */ + if (indxinfo->indisreplident) + { + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " INDEX %s;\n", + qindxname); + } + + appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); + + if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = indxinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .tablespace = indxinfo->tablespace, + .owner = tbinfo->rolname, + .description = "INDEX", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + if (indstatcolsarray) + free(indstatcolsarray); + if (indstatvalsarray) + free(indstatvalsarray); + } + + /* Dump Index Comments */ + if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "INDEX", qindxname, + tbinfo->dobj.namespace->dobj.name, + tbinfo->rolname, + indxinfo->dobj.catId, 0, + is_constraint ? indxinfo->indexconstraint : + indxinfo->dobj.dumpId); + + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qindxname); + free(qqindxname); +} + +/* + * dumpIndexAttach + * write out to fout a partitioned-index attachment clause + */ +static void +dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo) +{ + if (fout->dopt->dataOnly) + return; + + if (attachinfo->partitionIdx->dobj.dump & DUMP_COMPONENT_DEFINITION) + { + PQExpBuffer q = createPQExpBuffer(); + + appendPQExpBuffer(q, "ALTER INDEX %s ", + fmtQualifiedDumpable(attachinfo->parentIdx)); + appendPQExpBuffer(q, "ATTACH PARTITION %s;\n", + fmtQualifiedDumpable(attachinfo->partitionIdx)); + + /* + * There is no point in creating a drop query as the drop is done by + * index drop. (If you think to change this, see also + * _printTocEntry().) Although this object doesn't really have + * ownership as such, set the owner field anyway to ensure that the + * command is run by the correct role at restore time. + */ + ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = attachinfo->dobj.name, + .namespace = attachinfo->dobj.namespace->dobj.name, + .owner = attachinfo->parentIdx->indextable->rolname, + .description = "INDEX ATTACH", + .section = SECTION_POST_DATA, + .createStmt = q->data)); + + destroyPQExpBuffer(q); + } +} + +/* + * dumpStatisticsExt + * write out to fout an extended statistics object + */ +static void +dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer q; + PQExpBuffer delq; + PQExpBuffer query; + char *qstatsextname; + PGresult *res; + char *stxdef; + + /* Skip if not to be dumped */ + if (!statsextinfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + query = createPQExpBuffer(); + + qstatsextname = pg_strdup(fmtId(statsextinfo->dobj.name)); + + appendPQExpBuffer(query, "SELECT " + "pg_catalog.pg_get_statisticsobjdef('%u'::pg_catalog.oid)", + statsextinfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + stxdef = PQgetvalue(res, 0, 0); + + /* Result of pg_get_statisticsobjdef is complete except for semicolon */ + appendPQExpBuffer(q, "%s;\n", stxdef); + + /* + * We only issue an ALTER STATISTICS statement if the stxstattarget entry + * for this statistics object is non-negative (i.e. it's not the default + * value). + */ + if (statsextinfo->stattarget >= 0) + { + appendPQExpBuffer(q, "ALTER STATISTICS %s ", + fmtQualifiedDumpable(statsextinfo)); + appendPQExpBuffer(q, "SET STATISTICS %d;\n", + statsextinfo->stattarget); + } + + appendPQExpBuffer(delq, "DROP STATISTICS %s;\n", + fmtQualifiedDumpable(statsextinfo)); + + if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, statsextinfo->dobj.catId, + statsextinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = statsextinfo->dobj.name, + .namespace = statsextinfo->dobj.namespace->dobj.name, + .owner = statsextinfo->rolname, + .description = "STATISTICS", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + /* Dump Statistics Comments */ + if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "STATISTICS", qstatsextname, + statsextinfo->dobj.namespace->dobj.name, + statsextinfo->rolname, + statsextinfo->dobj.catId, 0, + statsextinfo->dobj.dumpId); + + PQclear(res); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + destroyPQExpBuffer(query); + free(qstatsextname); +} + +/* + * dumpConstraint + * write out to fout a user-defined constraint + */ +static void +dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = coninfo->contable; + PQExpBuffer q; + PQExpBuffer delq; + char *tag = NULL; + char *foreign; + + /* Skip if not to be dumped */ + if (!coninfo->dobj.dump || dopt->dataOnly) + return; + + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + foreign = tbinfo && + tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : ""; + + if (coninfo->contype == 'p' || + coninfo->contype == 'u' || + coninfo->contype == 'x') + { + /* Index-related constraint */ + IndxInfo *indxinfo; + int k; + + indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex); + + if (indxinfo == NULL) + fatal("missing index for constraint \"%s\"", + coninfo->dobj.name); + + if (dopt->binary_upgrade) + binary_upgrade_set_pg_class_oids(fout, q, + indxinfo->dobj.catId.oid, true); + + appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s\n", foreign, + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(q, " ADD CONSTRAINT %s ", + fmtId(coninfo->dobj.name)); + + if (coninfo->condef) + { + /* pg_get_constraintdef should have provided everything */ + appendPQExpBuffer(q, "%s;\n", coninfo->condef); + } + else + { + appendPQExpBuffer(q, "%s (", + coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE"); + for (k = 0; k < indxinfo->indnkeyattrs; k++) + { + int indkey = (int) indxinfo->indkeys[k]; + const char *attname; + + if (indkey == InvalidAttrNumber) + break; + attname = getAttrName(indkey, tbinfo); + + appendPQExpBuffer(q, "%s%s", + (k == 0) ? "" : ", ", + fmtId(attname)); + } + + if (indxinfo->indnkeyattrs < indxinfo->indnattrs) + appendPQExpBufferStr(q, ") INCLUDE ("); + + for (k = indxinfo->indnkeyattrs; k < indxinfo->indnattrs; k++) + { + int indkey = (int) indxinfo->indkeys[k]; + const char *attname; + + if (indkey == InvalidAttrNumber) + break; + attname = getAttrName(indkey, tbinfo); + + appendPQExpBuffer(q, "%s%s", + (k == indxinfo->indnkeyattrs) ? "" : ", ", + fmtId(attname)); + } + + appendPQExpBufferChar(q, ')'); + + if (nonemptyReloptions(indxinfo->indreloptions)) + { + appendPQExpBufferStr(q, " WITH ("); + appendReloptionsArrayAH(q, indxinfo->indreloptions, "", fout); + appendPQExpBufferChar(q, ')'); + } + + if (coninfo->condeferrable) + { + appendPQExpBufferStr(q, " DEFERRABLE"); + if (coninfo->condeferred) + appendPQExpBufferStr(q, " INITIALLY DEFERRED"); + } + + appendPQExpBufferStr(q, ";\n"); + } + + /* + * Append ALTER TABLE commands as needed to set properties that we + * only have ALTER TABLE syntax for. Keep this in sync with the + * similar code in dumpIndex! + */ + + /* If the index is clustered, we need to record that. */ + if (indxinfo->indisclustered) + { + appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " ON %s;\n", + fmtId(indxinfo->dobj.name)); + } + + /* If the index defines identity, we need to record that. */ + if (indxinfo->indisreplident) + { + appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING", + fmtQualifiedDumpable(tbinfo)); + /* index name is not qualified in this syntax */ + appendPQExpBuffer(q, " INDEX %s;\n", + fmtId(indxinfo->dobj.name)); + } + + /* Indexes can depend on extensions */ + append_depends_on_extension(fout, q, &indxinfo->dobj, + "pg_catalog.pg_class", "INDEX", + fmtQualifiedDumpable(indxinfo)); + + appendPQExpBuffer(delq, "ALTER %sTABLE ONLY %s ", foreign, + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", + fmtId(coninfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + + if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .tablespace = indxinfo->tablespace, + .owner = tbinfo->rolname, + .description = "CONSTRAINT", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + else if (coninfo->contype == 'f') + { + char *only; + + /* + * Foreign keys on partitioned tables are always declared as + * inheriting to partitions; for all other cases, emit them as + * applying ONLY directly to the named table, because that's how they + * work for regular inherited tables. + */ + only = tbinfo->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY "; + + /* + * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the + * current table data is not processed + */ + appendPQExpBuffer(q, "ALTER %sTABLE %s%s\n", foreign, + only, fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", + fmtId(coninfo->dobj.name), + coninfo->condef); + + appendPQExpBuffer(delq, "ALTER %sTABLE %s%s ", foreign, + only, fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", + fmtId(coninfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + + if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "FK CONSTRAINT", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + else if (coninfo->contype == 'c' && tbinfo) + { + /* CHECK constraint on a table */ + + /* Ignore if not to be dumped separately, or if it was inherited */ + if (coninfo->separate && coninfo->conislocal) + { + /* not ONLY since we want it to propagate to children */ + appendPQExpBuffer(q, "ALTER %sTABLE %s\n", foreign, + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", + fmtId(coninfo->dobj.name), + coninfo->condef); + + appendPQExpBuffer(delq, "ALTER %sTABLE %s ", foreign, + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", + fmtId(coninfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name); + + if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "CHECK CONSTRAINT", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + } + else if (coninfo->contype == 'c' && tbinfo == NULL) + { + /* CHECK constraint on a domain */ + TypeInfo *tyinfo = coninfo->condomain; + + /* Ignore if not to be dumped separately */ + if (coninfo->separate) + { + appendPQExpBuffer(q, "ALTER DOMAIN %s\n", + fmtQualifiedDumpable(tyinfo)); + appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n", + fmtId(coninfo->dobj.name), + coninfo->condef); + + appendPQExpBuffer(delq, "ALTER DOMAIN %s ", + fmtQualifiedDumpable(tyinfo)); + appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n", + fmtId(coninfo->dobj.name)); + + tag = psprintf("%s %s", tyinfo->dobj.name, coninfo->dobj.name); + + if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tyinfo->dobj.namespace->dobj.name, + .owner = tyinfo->rolname, + .description = "CHECK CONSTRAINT", + .section = SECTION_POST_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + } + } + else + { + fatal("unrecognized constraint type: %c", + coninfo->contype); + } + + /* Dump Constraint Comments --- only works for table constraints */ + if (tbinfo && coninfo->separate && + coninfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpTableConstraintComment(fout, coninfo); + + free(tag); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); +} + +/* + * dumpTableConstraintComment --- dump a constraint's comment if any + * + * This is split out because we need the function in two different places + * depending on whether the constraint is dumped as part of CREATE TABLE + * or as a separate ALTER command. + */ +static void +dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo) +{ + TableInfo *tbinfo = coninfo->contable; + PQExpBuffer conprefix = createPQExpBuffer(); + char *qtabname; + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); + + appendPQExpBuffer(conprefix, "CONSTRAINT %s ON", + fmtId(coninfo->dobj.name)); + + if (coninfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, conprefix->data, qtabname, + tbinfo->dobj.namespace->dobj.name, + tbinfo->rolname, + coninfo->dobj.catId, 0, + coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId); + + destroyPQExpBuffer(conprefix); + free(qtabname); +} + +/* + * findLastBuiltinOid_V71 - + * + * find the last built in oid + * + * For 7.1 through 8.0, we do this by retrieving datlastsysoid from the + * pg_database entry for the current database. (Note: current_database() + * requires 7.3; pg_dump requires 8.0 now.) + */ +static Oid +findLastBuiltinOid_V71(Archive *fout) +{ + PGresult *res; + Oid last_oid; + + res = ExecuteSqlQueryForSingleRow(fout, + "SELECT datlastsysoid FROM pg_database WHERE datname = current_database()"); + last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid"))); + PQclear(res); + + return last_oid; +} + +/* + * dumpSequence + * write the declaration (not data) of one user-defined sequence + */ +static void +dumpSequence(Archive *fout, const TableInfo *tbinfo) +{ + DumpOptions *dopt = fout->dopt; + PGresult *res; + char *startv, + *incby, + *maxv, + *minv, + *cache, + *seqtype; + bool cycled; + bool is_ascending; + int64 default_minv, + default_maxv; + char bufm[32], + bufx[32]; + PQExpBuffer query = createPQExpBuffer(); + PQExpBuffer delqry = createPQExpBuffer(); + char *qseqname; + + qseqname = pg_strdup(fmtId(tbinfo->dobj.name)); + + if (fout->remoteVersion >= 100000) + { + appendPQExpBuffer(query, + "SELECT format_type(seqtypid, NULL), " + "seqstart, seqincrement, " + "seqmax, seqmin, " + "seqcache, seqcycle " + "FROM pg_catalog.pg_sequence " + "WHERE seqrelid = '%u'::oid", + tbinfo->dobj.catId.oid); + } + else if (fout->remoteVersion >= 80400) + { + /* + * Before PostgreSQL 10, sequence metadata is in the sequence itself. + * + * Note: it might seem that 'bigint' potentially needs to be + * schema-qualified, but actually that's a keyword. + */ + appendPQExpBuffer(query, + "SELECT 'bigint' AS sequence_type, " + "start_value, increment_by, max_value, min_value, " + "cache_value, is_cycled FROM %s", + fmtQualifiedDumpable(tbinfo)); + } + else + { + appendPQExpBuffer(query, + "SELECT 'bigint' AS sequence_type, " + "0 AS start_value, increment_by, max_value, min_value, " + "cache_value, is_cycled FROM %s", + fmtQualifiedDumpable(tbinfo)); + } + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + if (PQntuples(res) != 1) + { + pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", + "query to get data of sequence \"%s\" returned %d rows (expected 1)", + PQntuples(res)), + tbinfo->dobj.name, PQntuples(res)); + exit_nicely(1); + } + + seqtype = PQgetvalue(res, 0, 0); + startv = PQgetvalue(res, 0, 1); + incby = PQgetvalue(res, 0, 2); + maxv = PQgetvalue(res, 0, 3); + minv = PQgetvalue(res, 0, 4); + cache = PQgetvalue(res, 0, 5); + cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0); + + /* Calculate default limits for a sequence of this type */ + is_ascending = (incby[0] != '-'); + if (strcmp(seqtype, "smallint") == 0) + { + default_minv = is_ascending ? 1 : PG_INT16_MIN; + default_maxv = is_ascending ? PG_INT16_MAX : -1; + } + else if (strcmp(seqtype, "integer") == 0) + { + default_minv = is_ascending ? 1 : PG_INT32_MIN; + default_maxv = is_ascending ? PG_INT32_MAX : -1; + } + else if (strcmp(seqtype, "bigint") == 0) + { + default_minv = is_ascending ? 1 : PG_INT64_MIN; + default_maxv = is_ascending ? PG_INT64_MAX : -1; + } + else + { + fatal("unrecognized sequence type: %s", seqtype); + default_minv = default_maxv = 0; /* keep compiler quiet */ + } + + /* + * 64-bit strtol() isn't very portable, so convert the limits to strings + * and compare that way. + */ + snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv); + snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv); + + /* Don't print minv/maxv if they match the respective default limit */ + if (strcmp(minv, bufm) == 0) + minv = NULL; + if (strcmp(maxv, bufx) == 0) + maxv = NULL; + + /* + * Identity sequences are not to be dropped separately. + */ + if (!tbinfo->is_identity_sequence) + { + appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n", + fmtQualifiedDumpable(tbinfo)); + } + + resetPQExpBuffer(query); + + if (dopt->binary_upgrade) + { + binary_upgrade_set_pg_class_oids(fout, query, + tbinfo->dobj.catId.oid, false); + + /* + * In older PG versions a sequence will have a pg_type entry, but v14 + * and up don't use that, so don't attempt to preserve the type OID. + */ + } + + if (tbinfo->is_identity_sequence) + { + TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab); + + appendPQExpBuffer(query, + "ALTER TABLE %s ", + fmtQualifiedDumpable(owning_tab)); + appendPQExpBuffer(query, + "ALTER COLUMN %s ADD GENERATED ", + fmtId(owning_tab->attnames[tbinfo->owning_col - 1])); + if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_ALWAYS) + appendPQExpBufferStr(query, "ALWAYS"); + else if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_BY_DEFAULT) + appendPQExpBufferStr(query, "BY DEFAULT"); + appendPQExpBuffer(query, " AS IDENTITY (\n SEQUENCE NAME %s\n", + fmtQualifiedDumpable(tbinfo)); + } + else + { + appendPQExpBuffer(query, + "CREATE SEQUENCE %s\n", + fmtQualifiedDumpable(tbinfo)); + + if (strcmp(seqtype, "bigint") != 0) + appendPQExpBuffer(query, " AS %s\n", seqtype); + } + + if (fout->remoteVersion >= 80400) + appendPQExpBuffer(query, " START WITH %s\n", startv); + + appendPQExpBuffer(query, " INCREMENT BY %s\n", incby); + + if (minv) + appendPQExpBuffer(query, " MINVALUE %s\n", minv); + else + appendPQExpBufferStr(query, " NO MINVALUE\n"); + + if (maxv) + appendPQExpBuffer(query, " MAXVALUE %s\n", maxv); + else + appendPQExpBufferStr(query, " NO MAXVALUE\n"); + + appendPQExpBuffer(query, + " CACHE %s%s", + cache, (cycled ? "\n CYCLE" : "")); + + if (tbinfo->is_identity_sequence) + appendPQExpBufferStr(query, "\n);\n"); + else + appendPQExpBufferStr(query, ";\n"); + + /* binary_upgrade: no need to clear TOAST table oid */ + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(query, &tbinfo->dobj, + "SEQUENCE", qseqname, + tbinfo->dobj.namespace->dobj.name); + + if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "SEQUENCE", + .section = SECTION_PRE_DATA, + .createStmt = query->data, + .dropStmt = delqry->data)); + + /* + * If the sequence is owned by a table column, emit the ALTER for it as a + * separate TOC entry immediately following the sequence's own entry. It's + * OK to do this rather than using full sorting logic, because the + * dependency that tells us it's owned will have forced the table to be + * created first. We can't just include the ALTER in the TOC entry + * because it will fail if we haven't reassigned the sequence owner to + * match the table's owner. + * + * We need not schema-qualify the table reference because both sequence + * and table must be in the same schema. + */ + if (OidIsValid(tbinfo->owning_tab) && !tbinfo->is_identity_sequence) + { + TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab); + + if (owning_tab == NULL) + fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found", + tbinfo->owning_tab, tbinfo->dobj.catId.oid); + + if (owning_tab->dobj.dump & DUMP_COMPONENT_DEFINITION) + { + resetPQExpBuffer(query); + appendPQExpBuffer(query, "ALTER SEQUENCE %s", + fmtQualifiedDumpable(tbinfo)); + appendPQExpBuffer(query, " OWNED BY %s", + fmtQualifiedDumpable(owning_tab)); + appendPQExpBuffer(query, ".%s;\n", + fmtId(owning_tab->attnames[tbinfo->owning_col - 1])); + + if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "SEQUENCE OWNED BY", + .section = SECTION_PRE_DATA, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + } + } + + /* Dump Sequence Comments and Security Labels */ + if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "SEQUENCE", qseqname, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); + + if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL) + dumpSecLabel(fout, "SEQUENCE", qseqname, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(delqry); + free(qseqname); +} + +/* + * dumpSequenceData + * write the data of one user-defined sequence + */ +static void +dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo) +{ + TableInfo *tbinfo = tdinfo->tdtable; + PGresult *res; + char *last; + bool called; + PQExpBuffer query = createPQExpBuffer(); + + appendPQExpBuffer(query, + "SELECT last_value, is_called FROM %s", + fmtQualifiedDumpable(tbinfo)); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + if (PQntuples(res) != 1) + { + pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", + "query to get data of sequence \"%s\" returned %d rows (expected 1)", + PQntuples(res)), + tbinfo->dobj.name, PQntuples(res)); + exit_nicely(1); + } + + last = PQgetvalue(res, 0, 0); + called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0); + + resetPQExpBuffer(query); + appendPQExpBufferStr(query, "SELECT pg_catalog.setval("); + appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout); + appendPQExpBuffer(query, ", %s, %s);\n", + last, (called ? "true" : "false")); + + if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = tbinfo->dobj.name, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "SEQUENCE SET", + .section = SECTION_DATA, + .createStmt = query->data, + .deps = &(tbinfo->dobj.dumpId), + .nDeps = 1)); + + PQclear(res); + + destroyPQExpBuffer(query); +} + +/* + * dumpTrigger + * write the declaration of one user-defined table trigger + */ +static void +dumpTrigger(Archive *fout, const TriggerInfo *tginfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = tginfo->tgtable; + PQExpBuffer query; + PQExpBuffer delqry; + PQExpBuffer trigprefix; + PQExpBuffer trigidentity; + char *qtabname; + char *tgargs; + size_t lentgargs; + const char *p; + int findx; + char *tag; + + /* + * we needn't check dobj.dump because TriggerInfo wouldn't have been + * created in the first place for non-dumpable triggers + */ + if (dopt->dataOnly) + return; + + query = createPQExpBuffer(); + delqry = createPQExpBuffer(); + trigprefix = createPQExpBuffer(); + trigidentity = createPQExpBuffer(); + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); + + appendPQExpBuffer(trigidentity, "%s ", fmtId(tginfo->dobj.name)); + appendPQExpBuffer(trigidentity, "ON %s", fmtQualifiedDumpable(tbinfo)); + + appendPQExpBuffer(delqry, "DROP TRIGGER %s;\n", trigidentity->data); + + if (tginfo->tgdef) + { + appendPQExpBuffer(query, "%s;\n", tginfo->tgdef); + } + else + { + if (tginfo->tgisconstraint) + { + appendPQExpBufferStr(query, "CREATE CONSTRAINT TRIGGER "); + appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname)); + } + else + { + appendPQExpBufferStr(query, "CREATE TRIGGER "); + appendPQExpBufferStr(query, fmtId(tginfo->dobj.name)); + } + appendPQExpBufferStr(query, "\n "); + + /* Trigger type */ + if (TRIGGER_FOR_BEFORE(tginfo->tgtype)) + appendPQExpBufferStr(query, "BEFORE"); + else if (TRIGGER_FOR_AFTER(tginfo->tgtype)) + appendPQExpBufferStr(query, "AFTER"); + else if (TRIGGER_FOR_INSTEAD(tginfo->tgtype)) + appendPQExpBufferStr(query, "INSTEAD OF"); + else + { + pg_log_error("unexpected tgtype value: %d", tginfo->tgtype); + exit_nicely(1); + } + + findx = 0; + if (TRIGGER_FOR_INSERT(tginfo->tgtype)) + { + appendPQExpBufferStr(query, " INSERT"); + findx++; + } + if (TRIGGER_FOR_DELETE(tginfo->tgtype)) + { + if (findx > 0) + appendPQExpBufferStr(query, " OR DELETE"); + else + appendPQExpBufferStr(query, " DELETE"); + findx++; + } + if (TRIGGER_FOR_UPDATE(tginfo->tgtype)) + { + if (findx > 0) + appendPQExpBufferStr(query, " OR UPDATE"); + else + appendPQExpBufferStr(query, " UPDATE"); + findx++; + } + if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype)) + { + if (findx > 0) + appendPQExpBufferStr(query, " OR TRUNCATE"); + else + appendPQExpBufferStr(query, " TRUNCATE"); + findx++; + } + appendPQExpBuffer(query, " ON %s\n", + fmtQualifiedDumpable(tbinfo)); + + if (tginfo->tgisconstraint) + { + if (OidIsValid(tginfo->tgconstrrelid)) + { + /* regclass output is already quoted */ + appendPQExpBuffer(query, " FROM %s\n ", + tginfo->tgconstrrelname); + } + if (!tginfo->tgdeferrable) + appendPQExpBufferStr(query, "NOT "); + appendPQExpBufferStr(query, "DEFERRABLE INITIALLY "); + if (tginfo->tginitdeferred) + appendPQExpBufferStr(query, "DEFERRED\n"); + else + appendPQExpBufferStr(query, "IMMEDIATE\n"); + } + + if (TRIGGER_FOR_ROW(tginfo->tgtype)) + appendPQExpBufferStr(query, " FOR EACH ROW\n "); + else + appendPQExpBufferStr(query, " FOR EACH STATEMENT\n "); + + /* regproc output is already sufficiently quoted */ + appendPQExpBuffer(query, "EXECUTE FUNCTION %s(", + tginfo->tgfname); + + tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs, + &lentgargs); + p = tgargs; + for (findx = 0; findx < tginfo->tgnargs; findx++) + { + /* find the embedded null that terminates this trigger argument */ + size_t tlen = strlen(p); + + if (p + tlen >= tgargs + lentgargs) + { + /* hm, not found before end of bytea value... */ + pg_log_error("invalid argument string (%s) for trigger \"%s\" on table \"%s\"", + tginfo->tgargs, + tginfo->dobj.name, + tbinfo->dobj.name); + exit_nicely(1); + } + + if (findx > 0) + appendPQExpBufferStr(query, ", "); + appendStringLiteralAH(query, p, fout); + p += tlen + 1; + } + free(tgargs); + appendPQExpBufferStr(query, ");\n"); + } + + /* Triggers can depend on extensions */ + append_depends_on_extension(fout, query, &tginfo->dobj, + "pg_catalog.pg_trigger", "TRIGGER", + trigidentity->data); + + if (tginfo->tgisinternal) + { + /* + * Triggers marked internal only appear here because their 'tgenabled' + * flag differs from its parent's. The trigger is created already, so + * remove the CREATE and replace it with an ALTER. (Clear out the + * DROP query too, so that pg_dump --create does not cause errors.) + */ + resetPQExpBuffer(query); + resetPQExpBuffer(delqry); + appendPQExpBuffer(query, "\nALTER %sTABLE %s ", + tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "", + fmtQualifiedDumpable(tbinfo)); + switch (tginfo->tgenabled) + { + case 'f': + case 'D': + appendPQExpBufferStr(query, "DISABLE"); + break; + case 't': + case 'O': + appendPQExpBufferStr(query, "ENABLE"); + break; + case 'R': + appendPQExpBufferStr(query, "ENABLE REPLICA"); + break; + case 'A': + appendPQExpBufferStr(query, "ENABLE ALWAYS"); + break; + } + appendPQExpBuffer(query, " TRIGGER %s;\n", + fmtId(tginfo->dobj.name)); + } + else if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O') + { + appendPQExpBuffer(query, "\nALTER %sTABLE %s ", + tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "", + fmtQualifiedDumpable(tbinfo)); + switch (tginfo->tgenabled) + { + case 'D': + case 'f': + appendPQExpBufferStr(query, "DISABLE"); + break; + case 'A': + appendPQExpBufferStr(query, "ENABLE ALWAYS"); + break; + case 'R': + appendPQExpBufferStr(query, "ENABLE REPLICA"); + break; + default: + appendPQExpBufferStr(query, "ENABLE"); + break; + } + appendPQExpBuffer(query, " TRIGGER %s;\n", + fmtId(tginfo->dobj.name)); + } + + appendPQExpBuffer(trigprefix, "TRIGGER %s ON", + fmtId(tginfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, tginfo->dobj.name); + + if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "TRIGGER", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .dropStmt = delqry->data)); + + if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, trigprefix->data, qtabname, + tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, + tginfo->dobj.catId, 0, tginfo->dobj.dumpId); + + free(tag); + destroyPQExpBuffer(query); + destroyPQExpBuffer(delqry); + destroyPQExpBuffer(trigprefix); + destroyPQExpBuffer(trigidentity); + free(qtabname); +} + +/* + * dumpEventTrigger + * write the declaration of one user-defined event trigger + */ +static void +dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer delqry; + char *qevtname; + + /* Skip if not to be dumped */ + if (!evtinfo->dobj.dump || dopt->dataOnly) + return; + + query = createPQExpBuffer(); + delqry = createPQExpBuffer(); + + qevtname = pg_strdup(fmtId(evtinfo->dobj.name)); + + appendPQExpBufferStr(query, "CREATE EVENT TRIGGER "); + appendPQExpBufferStr(query, qevtname); + appendPQExpBufferStr(query, " ON "); + appendPQExpBufferStr(query, fmtId(evtinfo->evtevent)); + + if (strcmp("", evtinfo->evttags) != 0) + { + appendPQExpBufferStr(query, "\n WHEN TAG IN ("); + appendPQExpBufferStr(query, evtinfo->evttags); + appendPQExpBufferChar(query, ')'); + } + + appendPQExpBufferStr(query, "\n EXECUTE FUNCTION "); + appendPQExpBufferStr(query, evtinfo->evtfname); + appendPQExpBufferStr(query, "();\n"); + + if (evtinfo->evtenabled != 'O') + { + appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ", + qevtname); + switch (evtinfo->evtenabled) + { + case 'D': + appendPQExpBufferStr(query, "DISABLE"); + break; + case 'A': + appendPQExpBufferStr(query, "ENABLE ALWAYS"); + break; + case 'R': + appendPQExpBufferStr(query, "ENABLE REPLICA"); + break; + default: + appendPQExpBufferStr(query, "ENABLE"); + break; + } + appendPQExpBufferStr(query, ";\n"); + } + + appendPQExpBuffer(delqry, "DROP EVENT TRIGGER %s;\n", + qevtname); + + if (dopt->binary_upgrade) + binary_upgrade_extension_member(query, &evtinfo->dobj, + "EVENT TRIGGER", qevtname, NULL); + + if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = evtinfo->dobj.name, + .owner = evtinfo->evtowner, + .description = "EVENT TRIGGER", + .section = SECTION_POST_DATA, + .createStmt = query->data, + .dropStmt = delqry->data)); + + if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "EVENT TRIGGER", qevtname, + NULL, evtinfo->evtowner, + evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(delqry); + free(qevtname); +} + +/* + * dumpRule + * Dump a rule + */ +static void +dumpRule(Archive *fout, const RuleInfo *rinfo) +{ + DumpOptions *dopt = fout->dopt; + TableInfo *tbinfo = rinfo->ruletable; + bool is_view; + PQExpBuffer query; + PQExpBuffer cmd; + PQExpBuffer delcmd; + PQExpBuffer ruleprefix; + char *qtabname; + PGresult *res; + char *tag; + + /* Skip if not to be dumped */ + if (!rinfo->dobj.dump || dopt->dataOnly) + return; + + /* + * If it is an ON SELECT rule that is created implicitly by CREATE VIEW, + * we do not want to dump it as a separate object. + */ + if (!rinfo->separate) + return; + + /* + * If it's an ON SELECT rule, we want to print it as a view definition, + * instead of a rule. + */ + is_view = (rinfo->ev_type == '1' && rinfo->is_instead); + + query = createPQExpBuffer(); + cmd = createPQExpBuffer(); + delcmd = createPQExpBuffer(); + ruleprefix = createPQExpBuffer(); + + qtabname = pg_strdup(fmtId(tbinfo->dobj.name)); + + if (is_view) + { + PQExpBuffer result; + + /* + * We need OR REPLACE here because we'll be replacing a dummy view. + * Otherwise this should look largely like the regular view dump code. + */ + appendPQExpBuffer(cmd, "CREATE OR REPLACE VIEW %s", + fmtQualifiedDumpable(tbinfo)); + if (nonemptyReloptions(tbinfo->reloptions)) + { + appendPQExpBufferStr(cmd, " WITH ("); + appendReloptionsArrayAH(cmd, tbinfo->reloptions, "", fout); + appendPQExpBufferChar(cmd, ')'); + } + result = createViewAsClause(fout, tbinfo); + appendPQExpBuffer(cmd, " AS\n%s", result->data); + destroyPQExpBuffer(result); + if (tbinfo->checkoption != NULL) + appendPQExpBuffer(cmd, "\n WITH %s CHECK OPTION", + tbinfo->checkoption); + appendPQExpBufferStr(cmd, ";\n"); + } + else + { + /* In the rule case, just print pg_get_ruledef's result verbatim */ + appendPQExpBuffer(query, + "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid)", + rinfo->dobj.catId.oid); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + if (PQntuples(res) != 1) + { + pg_log_error("query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned", + rinfo->dobj.name, tbinfo->dobj.name); + exit_nicely(1); + } + + printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0)); + + PQclear(res); + } + + /* + * Add the command to alter the rules replication firing semantics if it + * differs from the default. + */ + if (rinfo->ev_enabled != 'O') + { + appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtQualifiedDumpable(tbinfo)); + switch (rinfo->ev_enabled) + { + case 'A': + appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n", + fmtId(rinfo->dobj.name)); + break; + case 'R': + appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n", + fmtId(rinfo->dobj.name)); + break; + case 'D': + appendPQExpBuffer(cmd, "DISABLE RULE %s;\n", + fmtId(rinfo->dobj.name)); + break; + } + } + + if (is_view) + { + /* + * We can't DROP a view's ON SELECT rule. Instead, use CREATE OR + * REPLACE VIEW to replace the rule with something with minimal + * dependencies. + */ + PQExpBuffer result; + + appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s", + fmtQualifiedDumpable(tbinfo)); + result = createDummyViewAsClause(fout, tbinfo); + appendPQExpBuffer(delcmd, " AS\n%s;\n", result->data); + destroyPQExpBuffer(result); + } + else + { + appendPQExpBuffer(delcmd, "DROP RULE %s ", + fmtId(rinfo->dobj.name)); + appendPQExpBuffer(delcmd, "ON %s;\n", + fmtQualifiedDumpable(tbinfo)); + } + + appendPQExpBuffer(ruleprefix, "RULE %s ON", + fmtId(rinfo->dobj.name)); + + tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name); + + if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = tag, + .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = tbinfo->rolname, + .description = "RULE", + .section = SECTION_POST_DATA, + .createStmt = cmd->data, + .dropStmt = delcmd->data)); + + /* Dump rule comments */ + if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, ruleprefix->data, qtabname, + tbinfo->dobj.namespace->dobj.name, + tbinfo->rolname, + rinfo->dobj.catId, 0, rinfo->dobj.dumpId); + + free(tag); + destroyPQExpBuffer(query); + destroyPQExpBuffer(cmd); + destroyPQExpBuffer(delcmd); + destroyPQExpBuffer(ruleprefix); + free(qtabname); +} + +/* + * getExtensionMembership --- obtain extension membership data + * + * We need to identify objects that are extension members as soon as they're + * loaded, so that we can correctly determine whether they need to be dumped. + * Generally speaking, extension member objects will get marked as *not* to + * be dumped, as they will be recreated by the single CREATE EXTENSION + * command. However, in binary upgrade mode we still need to dump the members + * individually. + */ +void +getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], + int numExtensions) +{ + PQExpBuffer query; + PGresult *res; + int ntups, + nextmembers, + i; + int i_classid, + i_objid, + i_refobjid; + ExtensionMemberId *extmembers; + ExtensionInfo *ext; + + /* Nothing to do if no extensions */ + if (numExtensions == 0) + return; + + query = createPQExpBuffer(); + + /* refclassid constraint is redundant but may speed the search */ + appendPQExpBufferStr(query, "SELECT " + "classid, objid, refobjid " + "FROM pg_depend " + "WHERE refclassid = 'pg_extension'::regclass " + "AND deptype = 'e' " + "ORDER BY 3"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_classid = PQfnumber(res, "classid"); + i_objid = PQfnumber(res, "objid"); + i_refobjid = PQfnumber(res, "refobjid"); + + extmembers = (ExtensionMemberId *) pg_malloc(ntups * sizeof(ExtensionMemberId)); + nextmembers = 0; + + /* + * Accumulate data into extmembers[]. + * + * Since we ordered the SELECT by referenced ID, we can expect that + * multiple entries for the same extension will appear together; this + * saves on searches. + */ + ext = NULL; + + for (i = 0; i < ntups; i++) + { + CatalogId objId; + Oid extId; + + objId.tableoid = atooid(PQgetvalue(res, i, i_classid)); + objId.oid = atooid(PQgetvalue(res, i, i_objid)); + extId = atooid(PQgetvalue(res, i, i_refobjid)); + + if (ext == NULL || + ext->dobj.catId.oid != extId) + ext = findExtensionByOid(extId); + + if (ext == NULL) + { + /* shouldn't happen */ + pg_log_warning("could not find referenced extension %u", extId); + continue; + } + + extmembers[nextmembers].catId = objId; + extmembers[nextmembers].ext = ext; + nextmembers++; + } + + PQclear(res); + + /* Remember the data for use later */ + setExtensionMembership(extmembers, nextmembers); + + destroyPQExpBuffer(query); +} + +/* + * processExtensionTables --- deal with extension configuration tables + * + * There are two parts to this process: + * + * 1. Identify and create dump records for extension configuration tables. + * + * Extensions can mark tables as "configuration", which means that the user + * is able and expected to modify those tables after the extension has been + * loaded. For these tables, we dump out only the data- the structure is + * expected to be handled at CREATE EXTENSION time, including any indexes or + * foreign keys, which brings us to- + * + * 2. Record FK dependencies between configuration tables. + * + * Due to the FKs being created at CREATE EXTENSION time and therefore before + * the data is loaded, we have to work out what the best order for reloading + * the data is, to avoid FK violations when the tables are restored. This is + * not perfect- we can't handle circular dependencies and if any exist they + * will cause an invalid dump to be produced (though at least all of the data + * is included for a user to manually restore). This is currently documented + * but perhaps we can provide a better solution in the future. + */ +void +processExtensionTables(Archive *fout, ExtensionInfo extinfo[], + int numExtensions) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PGresult *res; + int ntups, + i; + int i_conrelid, + i_confrelid; + + /* Nothing to do if no extensions */ + if (numExtensions == 0) + return; + + /* + * Identify extension configuration tables and create TableDataInfo + * objects for them, ensuring their data will be dumped even though the + * tables themselves won't be. + * + * Note that we create TableDataInfo objects even in schemaOnly mode, ie, + * user data in a configuration table is treated like schema data. This + * seems appropriate since system data in a config table would get + * reloaded by CREATE EXTENSION. If the extension is not listed in the + * list of extensions to be included, none of its data is dumped. + */ + for (i = 0; i < numExtensions; i++) + { + ExtensionInfo *curext = &(extinfo[i]); + char *extconfig = curext->extconfig; + char *extcondition = curext->extcondition; + char **extconfigarray = NULL; + char **extconditionarray = NULL; + int nconfigitems = 0; + int nconditionitems = 0; + + /* + * Check if this extension is listed as to include in the dump. If + * not, any table data associated with it is discarded. + */ + if (extension_include_oids.head != NULL && + !simple_oid_list_member(&extension_include_oids, + curext->dobj.catId.oid)) + continue; + + if (strlen(extconfig) != 0 || strlen(extcondition) != 0) + { + int j; + + if (!parsePGArray(extconfig, &extconfigarray, &nconfigitems)) + fatal("could not parse extension configuration array"); + if (!parsePGArray(extcondition, &extconditionarray, &nconditionitems)) + fatal("could not parse extension condition array"); + if (nconfigitems != nconditionitems) + fatal("mismatched number of configurations and conditions for extension"); + + for (j = 0; j < nconfigitems; j++) + { + TableInfo *configtbl; + Oid configtbloid = atooid(extconfigarray[j]); + bool dumpobj = + curext->dobj.dump & DUMP_COMPONENT_DEFINITION; + + configtbl = findTableByOid(configtbloid); + if (configtbl == NULL) + continue; + + /* + * Tables of not-to-be-dumped extensions shouldn't be dumped + * unless the table or its schema is explicitly included + */ + if (!(curext->dobj.dump & DUMP_COMPONENT_DEFINITION)) + { + /* check table explicitly requested */ + if (table_include_oids.head != NULL && + simple_oid_list_member(&table_include_oids, + configtbloid)) + dumpobj = true; + + /* check table's schema explicitly requested */ + if (configtbl->dobj.namespace->dobj.dump & + DUMP_COMPONENT_DATA) + dumpobj = true; + } + + /* check table excluded by an exclusion switch */ + if (table_exclude_oids.head != NULL && + simple_oid_list_member(&table_exclude_oids, + configtbloid)) + dumpobj = false; + + /* check schema excluded by an exclusion switch */ + if (simple_oid_list_member(&schema_exclude_oids, + configtbl->dobj.namespace->dobj.catId.oid)) + dumpobj = false; + + if (dumpobj) + { + makeTableDataInfo(dopt, configtbl); + if (configtbl->dataObj != NULL) + { + if (strlen(extconditionarray[j]) > 0) + configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]); + } + } + } + } + if (extconfigarray) + free(extconfigarray); + if (extconditionarray) + free(extconditionarray); + } + + /* + * Now that all the TableDataInfo objects have been created for all the + * extensions, check their FK dependencies and register them to try and + * dump the data out in an order that they can be restored in. + * + * Note that this is not a problem for user tables as their FKs are + * recreated after the data has been loaded. + */ + + query = createPQExpBuffer(); + + printfPQExpBuffer(query, + "SELECT conrelid, confrelid " + "FROM pg_constraint " + "JOIN pg_depend ON (objid = confrelid) " + "WHERE contype = 'f' " + "AND refclassid = 'pg_extension'::regclass " + "AND classid = 'pg_class'::regclass;"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + ntups = PQntuples(res); + + i_conrelid = PQfnumber(res, "conrelid"); + i_confrelid = PQfnumber(res, "confrelid"); + + /* Now get the dependencies and register them */ + for (i = 0; i < ntups; i++) + { + Oid conrelid, + confrelid; + TableInfo *reftable, + *contable; + + conrelid = atooid(PQgetvalue(res, i, i_conrelid)); + confrelid = atooid(PQgetvalue(res, i, i_confrelid)); + contable = findTableByOid(conrelid); + reftable = findTableByOid(confrelid); + + if (reftable == NULL || + reftable->dataObj == NULL || + contable == NULL || + contable->dataObj == NULL) + continue; + + /* + * Make referencing TABLE_DATA object depend on the referenced table's + * TABLE_DATA object. + */ + addObjectDependency(&contable->dataObj->dobj, + reftable->dataObj->dobj.dumpId); + } + PQclear(res); + destroyPQExpBuffer(query); +} + +/* + * getDependencies --- obtain available dependency data + */ +static void +getDependencies(Archive *fout) +{ + PQExpBuffer query; + PGresult *res; + int ntups, + i; + int i_classid, + i_objid, + i_refclassid, + i_refobjid, + i_deptype; + DumpableObject *dobj, + *refdobj; + + pg_log_info("reading dependency data"); + + query = createPQExpBuffer(); + + /* + * Messy query to collect the dependency data we need. Note that we + * ignore the sub-object column, so that dependencies of or on a column + * look the same as dependencies of or on a whole table. + * + * PIN dependencies aren't interesting, and EXTENSION dependencies were + * already processed by getExtensionMembership. + */ + appendPQExpBufferStr(query, "SELECT " + "classid, objid, refclassid, refobjid, deptype " + "FROM pg_depend " + "WHERE deptype != 'p' AND deptype != 'e'\n"); + + /* + * Since we don't treat pg_amop entries as separate DumpableObjects, we + * have to translate their dependencies into dependencies of their parent + * opfamily. Ignore internal dependencies though, as those will point to + * their parent opclass, which we needn't consider here (and if we did, + * it'd just result in circular dependencies). Also, "loose" opfamily + * entries will have dependencies on their parent opfamily, which we + * should drop since they'd likewise become useless self-dependencies. + * (But be sure to keep deps on *other* opfamilies; see amopsortfamily.) + * + * Skip this for pre-8.3 source servers: pg_opfamily doesn't exist there, + * and the (known) cases where it would matter to have these dependencies + * can't arise anyway. + */ + if (fout->remoteVersion >= 80300) + { + appendPQExpBufferStr(query, "UNION ALL\n" + "SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype " + "FROM pg_depend d, pg_amop o " + "WHERE deptype NOT IN ('p', 'e', 'i') AND " + "classid = 'pg_amop'::regclass AND objid = o.oid " + "AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n"); + + /* Likewise for pg_amproc entries */ + appendPQExpBufferStr(query, "UNION ALL\n" + "SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype " + "FROM pg_depend d, pg_amproc p " + "WHERE deptype NOT IN ('p', 'e', 'i') AND " + "classid = 'pg_amproc'::regclass AND objid = p.oid " + "AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n"); + } + + /* Sort the output for efficiency below */ + appendPQExpBufferStr(query, "ORDER BY 1,2"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + i_classid = PQfnumber(res, "classid"); + i_objid = PQfnumber(res, "objid"); + i_refclassid = PQfnumber(res, "refclassid"); + i_refobjid = PQfnumber(res, "refobjid"); + i_deptype = PQfnumber(res, "deptype"); + + /* + * Since we ordered the SELECT by referencing ID, we can expect that + * multiple entries for the same object will appear together; this saves + * on searches. + */ + dobj = NULL; + + for (i = 0; i < ntups; i++) + { + CatalogId objId; + CatalogId refobjId; + char deptype; + + objId.tableoid = atooid(PQgetvalue(res, i, i_classid)); + objId.oid = atooid(PQgetvalue(res, i, i_objid)); + refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid)); + refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid)); + deptype = *(PQgetvalue(res, i, i_deptype)); + + if (dobj == NULL || + dobj->catId.tableoid != objId.tableoid || + dobj->catId.oid != objId.oid) + dobj = findObjectByCatalogId(objId); + + /* + * Failure to find objects mentioned in pg_depend is not unexpected, + * since for example we don't collect info about TOAST tables. + */ + if (dobj == NULL) + { +#ifdef NOT_USED + pg_log_warning("no referencing object %u %u", + objId.tableoid, objId.oid); +#endif + continue; + } + + refdobj = findObjectByCatalogId(refobjId); + + if (refdobj == NULL) + { +#ifdef NOT_USED + pg_log_warning("no referenced object %u %u", + refobjId.tableoid, refobjId.oid); +#endif + continue; + } + + /* + * For 'x' dependencies, mark the object for later; we still add the + * normal dependency, for possible ordering purposes. Currently + * pg_dump_sort.c knows to put extensions ahead of all object types + * that could possibly depend on them, but this is safer. + */ + if (deptype == 'x') + dobj->depends_on_ext = true; + + /* + * Ordinarily, table rowtypes have implicit dependencies on their + * tables. However, for a composite type the implicit dependency goes + * the other way in pg_depend; which is the right thing for DROP but + * it doesn't produce the dependency ordering we need. So in that one + * case, we reverse the direction of the dependency. + */ + if (deptype == 'i' && + dobj->objType == DO_TABLE && + refdobj->objType == DO_TYPE) + addObjectDependency(refdobj, dobj->dumpId); + else + /* normal case */ + addObjectDependency(dobj, refdobj->dumpId); + } + + PQclear(res); + + destroyPQExpBuffer(query); +} + + +/* + * createBoundaryObjects - create dummy DumpableObjects to represent + * dump section boundaries. + */ +static DumpableObject * +createBoundaryObjects(void) +{ + DumpableObject *dobjs; + + dobjs = (DumpableObject *) pg_malloc(2 * sizeof(DumpableObject)); + + dobjs[0].objType = DO_PRE_DATA_BOUNDARY; + dobjs[0].catId = nilCatalogId; + AssignDumpId(dobjs + 0); + dobjs[0].name = pg_strdup("PRE-DATA BOUNDARY"); + + dobjs[1].objType = DO_POST_DATA_BOUNDARY; + dobjs[1].catId = nilCatalogId; + AssignDumpId(dobjs + 1); + dobjs[1].name = pg_strdup("POST-DATA BOUNDARY"); + + return dobjs; +} + +/* + * addBoundaryDependencies - add dependencies as needed to enforce the dump + * section boundaries. + */ +static void +addBoundaryDependencies(DumpableObject **dobjs, int numObjs, + DumpableObject *boundaryObjs) +{ + DumpableObject *preDataBound = boundaryObjs + 0; + DumpableObject *postDataBound = boundaryObjs + 1; + int i; + + for (i = 0; i < numObjs; i++) + { + DumpableObject *dobj = dobjs[i]; + + /* + * The classification of object types here must match the SECTION_xxx + * values assigned during subsequent ArchiveEntry calls! + */ + switch (dobj->objType) + { + case DO_NAMESPACE: + case DO_EXTENSION: + case DO_TYPE: + case DO_SHELL_TYPE: + case DO_FUNC: + case DO_AGG: + case DO_OPERATOR: + case DO_ACCESS_METHOD: + case DO_OPCLASS: + case DO_OPFAMILY: + case DO_COLLATION: + case DO_CONVERSION: + case DO_TABLE: + case DO_TABLE_ATTACH: + case DO_ATTRDEF: + case DO_PROCLANG: + case DO_CAST: + case DO_DUMMY_TYPE: + case DO_TSPARSER: + case DO_TSDICT: + case DO_TSTEMPLATE: + case DO_TSCONFIG: + case DO_FDW: + case DO_FOREIGN_SERVER: + case DO_TRANSFORM: + case DO_BLOB: + /* Pre-data objects: must come before the pre-data boundary */ + addObjectDependency(preDataBound, dobj->dumpId); + break; + case DO_TABLE_DATA: + case DO_SEQUENCE_SET: + case DO_BLOB_DATA: + /* Data objects: must come between the boundaries */ + addObjectDependency(dobj, preDataBound->dumpId); + addObjectDependency(postDataBound, dobj->dumpId); + break; + case DO_INDEX: + case DO_INDEX_ATTACH: + case DO_STATSEXT: + case DO_REFRESH_MATVIEW: + case DO_TRIGGER: + case DO_EVENT_TRIGGER: + case DO_DEFAULT_ACL: + case DO_POLICY: + case DO_PUBLICATION: + case DO_PUBLICATION_REL: + case DO_SUBSCRIPTION: + /* Post-data objects: must come after the post-data boundary */ + addObjectDependency(dobj, postDataBound->dumpId); + break; + case DO_RULE: + /* Rules are post-data, but only if dumped separately */ + if (((RuleInfo *) dobj)->separate) + addObjectDependency(dobj, postDataBound->dumpId); + break; + case DO_CONSTRAINT: + case DO_FK_CONSTRAINT: + /* Constraints are post-data, but only if dumped separately */ + if (((ConstraintInfo *) dobj)->separate) + addObjectDependency(dobj, postDataBound->dumpId); + break; + case DO_PRE_DATA_BOUNDARY: + /* nothing to do */ + break; + case DO_POST_DATA_BOUNDARY: + /* must come after the pre-data boundary */ + addObjectDependency(dobj, preDataBound->dumpId); + break; + } + } +} + + +/* + * BuildArchiveDependencies - create dependency data for archive TOC entries + * + * The raw dependency data obtained by getDependencies() is not terribly + * useful in an archive dump, because in many cases there are dependency + * chains linking through objects that don't appear explicitly in the dump. + * For example, a view will depend on its _RETURN rule while the _RETURN rule + * will depend on other objects --- but the rule will not appear as a separate + * object in the dump. We need to adjust the view's dependencies to include + * whatever the rule depends on that is included in the dump. + * + * Just to make things more complicated, there are also "special" dependencies + * such as the dependency of a TABLE DATA item on its TABLE, which we must + * not rearrange because pg_restore knows that TABLE DATA only depends on + * its table. In these cases we must leave the dependencies strictly as-is + * even if they refer to not-to-be-dumped objects. + * + * To handle this, the convention is that "special" dependencies are created + * during ArchiveEntry calls, and an archive TOC item that has any such + * entries will not be touched here. Otherwise, we recursively search the + * DumpableObject data structures to build the correct dependencies for each + * archive TOC item. + */ +static void +BuildArchiveDependencies(Archive *fout) +{ + ArchiveHandle *AH = (ArchiveHandle *) fout; + TocEntry *te; + + /* Scan all TOC entries in the archive */ + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + DumpableObject *dobj; + DumpId *dependencies; + int nDeps; + int allocDeps; + + /* No need to process entries that will not be dumped */ + if (te->reqs == 0) + continue; + /* Ignore entries that already have "special" dependencies */ + if (te->nDeps > 0) + continue; + /* Otherwise, look up the item's original DumpableObject, if any */ + dobj = findObjectByDumpId(te->dumpId); + if (dobj == NULL) + continue; + /* No work if it has no dependencies */ + if (dobj->nDeps <= 0) + continue; + /* Set up work array */ + allocDeps = 64; + dependencies = (DumpId *) pg_malloc(allocDeps * sizeof(DumpId)); + nDeps = 0; + /* Recursively find all dumpable dependencies */ + findDumpableDependencies(AH, dobj, + &dependencies, &nDeps, &allocDeps); + /* And save 'em ... */ + if (nDeps > 0) + { + dependencies = (DumpId *) pg_realloc(dependencies, + nDeps * sizeof(DumpId)); + te->dependencies = dependencies; + te->nDeps = nDeps; + } + else + free(dependencies); + } +} + +/* Recursive search subroutine for BuildArchiveDependencies */ +static void +findDumpableDependencies(ArchiveHandle *AH, const DumpableObject *dobj, + DumpId **dependencies, int *nDeps, int *allocDeps) +{ + int i; + + /* + * Ignore section boundary objects: if we search through them, we'll + * report lots of bogus dependencies. + */ + if (dobj->objType == DO_PRE_DATA_BOUNDARY || + dobj->objType == DO_POST_DATA_BOUNDARY) + return; + + for (i = 0; i < dobj->nDeps; i++) + { + DumpId depid = dobj->dependencies[i]; + + if (TocIDRequired(AH, depid) != 0) + { + /* Object will be dumped, so just reference it as a dependency */ + if (*nDeps >= *allocDeps) + { + *allocDeps *= 2; + *dependencies = (DumpId *) pg_realloc(*dependencies, + *allocDeps * sizeof(DumpId)); + } + (*dependencies)[*nDeps] = depid; + (*nDeps)++; + } + else + { + /* + * Object will not be dumped, so recursively consider its deps. We + * rely on the assumption that sortDumpableObjects already broke + * any dependency loops, else we might recurse infinitely. + */ + DumpableObject *otherdobj = findObjectByDumpId(depid); + + if (otherdobj) + findDumpableDependencies(AH, otherdobj, + dependencies, nDeps, allocDeps); + } + } +} + + +/* + * getFormattedTypeName - retrieve a nicely-formatted type name for the + * given type OID. + * + * This does not guarantee to schema-qualify the output, so it should not + * be used to create the target object name for CREATE or ALTER commands. + * + * Note that the result is cached and must not be freed by the caller. + */ +static const char * +getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts) +{ + TypeInfo *typeInfo; + char *result; + PQExpBuffer query; + PGresult *res; + + if (oid == 0) + { + if ((opts & zeroAsStar) != 0) + return "*"; + else if ((opts & zeroAsNone) != 0) + return "NONE"; + } + + /* see if we have the result cached in the type's TypeInfo record */ + typeInfo = findTypeByOid(oid); + if (typeInfo && typeInfo->ftypname) + return typeInfo->ftypname; + + query = createPQExpBuffer(); + appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)", + oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + /* result of format_type is already quoted */ + result = pg_strdup(PQgetvalue(res, 0, 0)); + + PQclear(res); + destroyPQExpBuffer(query); + + /* + * Cache the result for re-use in later requests, if possible. If we + * don't have a TypeInfo for the type, the string will be leaked once the + * caller is done with it ... but that case really should not happen, so + * leaking if it does seems acceptable. + */ + if (typeInfo) + typeInfo->ftypname = result; + + return result; +} + +/* + * Return a column list clause for the given relation. + * + * Special case: if there are no undropped columns in the relation, return + * "", not an invalid "()" column list. + */ +static const char * +fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer) +{ + int numatts = ti->numatts; + char **attnames = ti->attnames; + bool *attisdropped = ti->attisdropped; + char *attgenerated = ti->attgenerated; + bool needComma; + int i; + + appendPQExpBufferChar(buffer, '('); + needComma = false; + for (i = 0; i < numatts; i++) + { + if (attisdropped[i]) + continue; + if (attgenerated[i]) + continue; + if (needComma) + appendPQExpBufferStr(buffer, ", "); + appendPQExpBufferStr(buffer, fmtId(attnames[i])); + needComma = true; + } + + if (!needComma) + return ""; /* no undropped columns */ + + appendPQExpBufferChar(buffer, ')'); + return buffer->data; +} + +/* + * Check if a reloptions array is nonempty. + */ +static bool +nonemptyReloptions(const char *reloptions) +{ + /* Don't want to print it if it's just "{}" */ + return (reloptions != NULL && strlen(reloptions) > 2); +} + +/* + * Format a reloptions array and append it to the given buffer. + * + * "prefix" is prepended to the option names; typically it's "" or "toast.". + */ +static void +appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions, + const char *prefix, Archive *fout) +{ + bool res; + + res = appendReloptionsArray(buffer, reloptions, prefix, fout->encoding, + fout->std_strings); + if (!res) + pg_log_warning("could not parse reloptions array"); +} diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h new file mode 100644 index 0000000..8b2a8b6 --- /dev/null +++ b/src/bin/pg_dump/pg_dump.h @@ -0,0 +1,739 @@ +/*------------------------------------------------------------------------- + * + * pg_dump.h + * Common header file for the pg_dump utility + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/pg_dump.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DUMP_H +#define PG_DUMP_H + +#include "pg_backup.h" + + +#define oidcmp(x,y) ( ((x) < (y) ? -1 : ((x) > (y)) ? 1 : 0) ) + +/* + * The data structures used to store system catalog information. Every + * dumpable object is a subclass of DumpableObject. + * + * NOTE: the structures described here live for the entire pg_dump run; + * and in most cases we make a struct for every object we can find in the + * catalogs, not only those we are actually going to dump. Hence, it's + * best to store a minimal amount of per-object info in these structs, + * and retrieve additional per-object info when and if we dump a specific + * object. In particular, try to avoid retrieving expensive-to-compute + * information until it's known to be needed. We do, however, have to + * store enough info to determine whether an object should be dumped and + * what order to dump in. + */ + +typedef enum +{ + /* When modifying this enum, update priority tables in pg_dump_sort.c! */ + DO_NAMESPACE, + DO_EXTENSION, + DO_TYPE, + DO_SHELL_TYPE, + DO_FUNC, + DO_AGG, + DO_OPERATOR, + DO_ACCESS_METHOD, + DO_OPCLASS, + DO_OPFAMILY, + DO_COLLATION, + DO_CONVERSION, + DO_TABLE, + DO_TABLE_ATTACH, + DO_ATTRDEF, + DO_INDEX, + DO_INDEX_ATTACH, + DO_STATSEXT, + DO_RULE, + DO_TRIGGER, + DO_CONSTRAINT, + DO_FK_CONSTRAINT, /* see note for ConstraintInfo */ + DO_PROCLANG, + DO_CAST, + DO_TABLE_DATA, + DO_SEQUENCE_SET, + DO_DUMMY_TYPE, + DO_TSPARSER, + DO_TSDICT, + DO_TSTEMPLATE, + DO_TSCONFIG, + DO_FDW, + DO_FOREIGN_SERVER, + DO_DEFAULT_ACL, + DO_TRANSFORM, + DO_BLOB, + DO_BLOB_DATA, + DO_PRE_DATA_BOUNDARY, + DO_POST_DATA_BOUNDARY, + DO_EVENT_TRIGGER, + DO_REFRESH_MATVIEW, + DO_POLICY, + DO_PUBLICATION, + DO_PUBLICATION_REL, + DO_SUBSCRIPTION +} DumpableObjectType; + +/* component types of an object which can be selected for dumping */ +typedef uint32 DumpComponents; /* a bitmask of dump object components */ +#define DUMP_COMPONENT_NONE (0) +#define DUMP_COMPONENT_DEFINITION (1 << 0) +#define DUMP_COMPONENT_DATA (1 << 1) +#define DUMP_COMPONENT_COMMENT (1 << 2) +#define DUMP_COMPONENT_SECLABEL (1 << 3) +#define DUMP_COMPONENT_ACL (1 << 4) +#define DUMP_COMPONENT_POLICY (1 << 5) +#define DUMP_COMPONENT_USERMAP (1 << 6) +#define DUMP_COMPONENT_ALL (0xFFFF) + +/* + * component types which require us to obtain a lock on the table + * + * Note that some components only require looking at the information + * in the pg_catalog tables and, for those components, we do not need + * to lock the table. Be careful here though- some components use + * server-side functions which pull the latest information from + * SysCache and in those cases we *do* need to lock the table. + * + * We do not need locks for the COMMENT and SECLABEL components as + * those simply query their associated tables without using any + * server-side functions. We do not need locks for the ACL component + * as we pull that information from pg_class without using any + * server-side functions that use SysCache. The USERMAP component + * is only relevant for FOREIGN SERVERs and not tables, so no sense + * locking a table for that either (that can happen if we are going + * to dump "ALL" components for a table). + * + * We DO need locks for DEFINITION, due to various server-side + * functions that are used and POLICY due to pg_get_expr(). We set + * this up to grab the lock except in the cases we know to be safe. + */ +#define DUMP_COMPONENTS_REQUIRING_LOCK (\ + DUMP_COMPONENT_DEFINITION |\ + DUMP_COMPONENT_DATA |\ + DUMP_COMPONENT_POLICY) + +typedef struct _dumpableObject +{ + DumpableObjectType objType; + CatalogId catId; /* zero if not a cataloged object */ + DumpId dumpId; /* assigned by AssignDumpId() */ + char *name; /* object name (should never be NULL) */ + struct _namespaceInfo *namespace; /* containing namespace, or NULL */ + DumpComponents dump; /* bitmask of components to dump */ + DumpComponents dump_contains; /* as above, but for contained objects */ + bool ext_member; /* true if object is member of extension */ + bool depends_on_ext; /* true if object depends on an extension */ + DumpId *dependencies; /* dumpIds of objects this one depends on */ + int nDeps; /* number of valid dependencies */ + int allocDeps; /* allocated size of dependencies[] */ +} DumpableObject; + +typedef struct _namespaceInfo +{ + DumpableObject dobj; + char *rolname; /* name of owner, or empty string */ + char *nspacl; + char *rnspacl; + char *initnspacl; + char *initrnspacl; +} NamespaceInfo; + +typedef struct _extensionInfo +{ + DumpableObject dobj; + char *namespace; /* schema containing extension's objects */ + bool relocatable; + char *extversion; + char *extconfig; /* info about configuration tables */ + char *extcondition; +} ExtensionInfo; + +typedef struct _typeInfo +{ + DumpableObject dobj; + + /* + * Note: dobj.name is the raw pg_type.typname entry. ftypname is the + * result of format_type(), which will be quoted if needed, and might be + * schema-qualified too. + */ + char *ftypname; + char *rolname; /* name of owner, or empty string */ + char *typacl; + char *rtypacl; + char *inittypacl; + char *initrtypacl; + Oid typelem; + Oid typrelid; + char typrelkind; /* 'r', 'v', 'c', etc */ + char typtype; /* 'b', 'c', etc */ + bool isArray; /* true if auto-generated array type */ + bool isMultirange; /* true if auto-generated multirange type */ + bool isDefined; /* true if typisdefined */ + /* If needed, we'll create a "shell type" entry for it; link that here: */ + struct _shellTypeInfo *shellType; /* shell-type entry, or NULL */ + /* If it's a domain, we store links to its constraints here: */ + int nDomChecks; + struct _constraintInfo *domChecks; +} TypeInfo; + +typedef struct _shellTypeInfo +{ + DumpableObject dobj; + + TypeInfo *baseType; /* back link to associated base type */ +} ShellTypeInfo; + +typedef struct _funcInfo +{ + DumpableObject dobj; + char *rolname; /* name of owner, or empty string */ + Oid lang; + int nargs; + Oid *argtypes; + Oid prorettype; + char *proacl; + char *rproacl; + char *initproacl; + char *initrproacl; +} FuncInfo; + +/* AggInfo is a superset of FuncInfo */ +typedef struct _aggInfo +{ + FuncInfo aggfn; + /* we don't require any other fields at the moment */ +} AggInfo; + +typedef struct _oprInfo +{ + DumpableObject dobj; + char *rolname; + char oprkind; + Oid oprcode; +} OprInfo; + +typedef struct _accessMethodInfo +{ + DumpableObject dobj; + char amtype; + char *amhandler; +} AccessMethodInfo; + +typedef struct _opclassInfo +{ + DumpableObject dobj; + char *rolname; +} OpclassInfo; + +typedef struct _opfamilyInfo +{ + DumpableObject dobj; + char *rolname; +} OpfamilyInfo; + +typedef struct _collInfo +{ + DumpableObject dobj; + char *rolname; +} CollInfo; + +typedef struct _convInfo +{ + DumpableObject dobj; + char *rolname; +} ConvInfo; + +typedef struct _tableInfo +{ + /* + * These fields are collected for every table in the database. + */ + DumpableObject dobj; + char *rolname; /* name of owner, or empty string */ + char *relacl; + char *rrelacl; + char *initrelacl; + char *initrrelacl; + char relkind; + char relpersistence; /* relation persistence */ + bool relispopulated; /* relation is populated */ + char relreplident; /* replica identifier */ + char *reltablespace; /* relation tablespace */ + char *reloptions; /* options specified by WITH (...) */ + char *checkoption; /* WITH CHECK OPTION, if any */ + char *toast_reloptions; /* WITH options for the TOAST table */ + bool hasindex; /* does it have any indexes? */ + bool hasrules; /* does it have any rules? */ + bool hastriggers; /* does it have any triggers? */ + bool rowsec; /* is row security enabled? */ + bool forcerowsec; /* is row security forced? */ + bool hasoids; /* does it have OIDs? */ + uint32 frozenxid; /* table's relfrozenxid */ + uint32 minmxid; /* table's relminmxid */ + Oid toast_oid; /* toast table's OID, or 0 if none */ + uint32 toast_frozenxid; /* toast table's relfrozenxid, if any */ + uint32 toast_minmxid; /* toast table's relminmxid */ + int ncheck; /* # of CHECK expressions */ + char *reloftype; /* underlying type for typed table */ + Oid foreign_server; /* foreign server oid, if applicable */ + /* these two are set only if table is a sequence owned by a column: */ + Oid owning_tab; /* OID of table owning sequence */ + int owning_col; /* attr # of column owning sequence */ + bool is_identity_sequence; + int relpages; /* table's size in pages (from pg_class) */ + + bool interesting; /* true if need to collect more data */ + bool dummy_view; /* view's real definition must be postponed */ + bool postponed_def; /* matview must be postponed into post-data */ + bool ispartition; /* is table a partition? */ + + /* + * These fields are computed only if we decide the table is interesting + * (it's either a table to dump, or a direct parent of a dumpable table). + */ + int numatts; /* number of attributes */ + char **attnames; /* the attribute names */ + char **atttypnames; /* attribute type names */ + int *atttypmod; /* type-specific type modifiers */ + int *attstattarget; /* attribute statistics targets */ + char *attstorage; /* attribute storage scheme */ + char *typstorage; /* type storage scheme */ + bool *attisdropped; /* true if attr is dropped; don't dump it */ + char *attidentity; + char *attgenerated; + int *attlen; /* attribute length, used by binary_upgrade */ + char *attalign; /* attribute align, used by binary_upgrade */ + bool *attislocal; /* true if attr has local definition */ + char **attoptions; /* per-attribute options */ + Oid *attcollation; /* per-attribute collation selection */ + char *attcompression; /* per-attribute compression method */ + char **attfdwoptions; /* per-attribute fdw options */ + char **attmissingval; /* per attribute missing value */ + bool *notnull; /* NOT NULL constraints on attributes */ + bool *inhNotNull; /* true if NOT NULL is inherited */ + struct _attrDefInfo **attrdefs; /* DEFAULT expressions */ + struct _constraintInfo *checkexprs; /* CHECK constraints */ + char *partkeydef; /* partition key definition */ + char *partbound; /* partition bound definition */ + bool needs_override; /* has GENERATED ALWAYS AS IDENTITY */ + char *amname; /* relation access method */ + + /* + * Stuff computed only for dumpable tables. + */ + int numParents; /* number of (immediate) parent tables */ + struct _tableInfo **parents; /* TableInfos of immediate parents */ + int numIndexes; /* number of indexes */ + struct _indxInfo *indexes; /* indexes */ + struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */ + int numTriggers; /* number of triggers for table */ + struct _triggerInfo *triggers; /* array of TriggerInfo structs */ +} TableInfo; + +typedef struct _tableAttachInfo +{ + DumpableObject dobj; + TableInfo *parentTbl; /* link to partitioned table */ + TableInfo *partitionTbl; /* link to partition */ +} TableAttachInfo; + +typedef struct _attrDefInfo +{ + DumpableObject dobj; /* note: dobj.name is name of table */ + TableInfo *adtable; /* link to table of attribute */ + int adnum; + char *adef_expr; /* decompiled DEFAULT expression */ + bool separate; /* true if must dump as separate item */ +} AttrDefInfo; + +typedef struct _tableDataInfo +{ + DumpableObject dobj; + TableInfo *tdtable; /* link to table to dump */ + char *filtercond; /* WHERE condition to limit rows dumped */ +} TableDataInfo; + +typedef struct _indxInfo +{ + DumpableObject dobj; + TableInfo *indextable; /* link to table the index is for */ + char *indexdef; + char *tablespace; /* tablespace in which index is stored */ + char *indreloptions; /* options specified by WITH (...) */ + char *indstatcols; /* column numbers with statistics */ + char *indstatvals; /* statistic values for columns */ + int indnkeyattrs; /* number of index key attributes */ + int indnattrs; /* total number of index attributes */ + Oid *indkeys; /* In spite of the name 'indkeys' this field + * contains both key and nonkey attributes */ + bool indisclustered; + bool indisreplident; + Oid parentidx; /* if a partition, parent index OID */ + SimplePtrList partattaches; /* if partitioned, partition attach objects */ + + /* if there is an associated constraint object, its dumpId: */ + DumpId indexconstraint; +} IndxInfo; + +typedef struct _indexAttachInfo +{ + DumpableObject dobj; + IndxInfo *parentIdx; /* link to index on partitioned table */ + IndxInfo *partitionIdx; /* link to index on partition */ +} IndexAttachInfo; + +typedef struct _statsExtInfo +{ + DumpableObject dobj; + char *rolname; /* name of owner, or empty string */ + int stattarget; /* statistics target */ +} StatsExtInfo; + +typedef struct _ruleInfo +{ + DumpableObject dobj; + TableInfo *ruletable; /* link to table the rule is for */ + char ev_type; + bool is_instead; + char ev_enabled; + bool separate; /* true if must dump as separate item */ + /* separate is always true for non-ON SELECT rules */ +} RuleInfo; + +typedef struct _triggerInfo +{ + DumpableObject dobj; + TableInfo *tgtable; /* link to table the trigger is for */ + char *tgfname; + int tgtype; + int tgnargs; + char *tgargs; + bool tgisconstraint; + char *tgconstrname; + Oid tgconstrrelid; + char *tgconstrrelname; + char tgenabled; + bool tgisinternal; + bool tgdeferrable; + bool tginitdeferred; + char *tgdef; +} TriggerInfo; + +typedef struct _evttriggerInfo +{ + DumpableObject dobj; + char *evtname; + char *evtevent; + char *evtowner; + char *evttags; + char *evtfname; + char evtenabled; +} EventTriggerInfo; + +/* + * struct ConstraintInfo is used for all constraint types. However we + * use a different objType for foreign key constraints, to make it easier + * to sort them the way we want. + * + * Note: condeferrable and condeferred are currently only valid for + * unique/primary-key constraints. Otherwise that info is in condef. + */ +typedef struct _constraintInfo +{ + DumpableObject dobj; + TableInfo *contable; /* NULL if domain constraint */ + TypeInfo *condomain; /* NULL if table constraint */ + char contype; + char *condef; /* definition, if CHECK or FOREIGN KEY */ + Oid confrelid; /* referenced table, if FOREIGN KEY */ + DumpId conindex; /* identifies associated index if any */ + bool condeferrable; /* true if constraint is DEFERRABLE */ + bool condeferred; /* true if constraint is INITIALLY DEFERRED */ + bool conislocal; /* true if constraint has local definition */ + bool separate; /* true if must dump as separate item */ +} ConstraintInfo; + +typedef struct _procLangInfo +{ + DumpableObject dobj; + bool lanpltrusted; + Oid lanplcallfoid; + Oid laninline; + Oid lanvalidator; + char *lanacl; + char *rlanacl; + char *initlanacl; + char *initrlanacl; + char *lanowner; /* name of owner, or empty string */ +} ProcLangInfo; + +typedef struct _castInfo +{ + DumpableObject dobj; + Oid castsource; + Oid casttarget; + Oid castfunc; + char castcontext; + char castmethod; +} CastInfo; + +typedef struct _transformInfo +{ + DumpableObject dobj; + Oid trftype; + Oid trflang; + Oid trffromsql; + Oid trftosql; +} TransformInfo; + +/* InhInfo isn't a DumpableObject, just temporary state */ +typedef struct _inhInfo +{ + Oid inhrelid; /* OID of a child table */ + Oid inhparent; /* OID of its parent */ +} InhInfo; + +typedef struct _prsInfo +{ + DumpableObject dobj; + Oid prsstart; + Oid prstoken; + Oid prsend; + Oid prsheadline; + Oid prslextype; +} TSParserInfo; + +typedef struct _dictInfo +{ + DumpableObject dobj; + char *rolname; + Oid dicttemplate; + char *dictinitoption; +} TSDictInfo; + +typedef struct _tmplInfo +{ + DumpableObject dobj; + Oid tmplinit; + Oid tmpllexize; +} TSTemplateInfo; + +typedef struct _cfgInfo +{ + DumpableObject dobj; + char *rolname; + Oid cfgparser; +} TSConfigInfo; + +typedef struct _fdwInfo +{ + DumpableObject dobj; + char *rolname; + char *fdwhandler; + char *fdwvalidator; + char *fdwoptions; + char *fdwacl; + char *rfdwacl; + char *initfdwacl; + char *initrfdwacl; +} FdwInfo; + +typedef struct _foreignServerInfo +{ + DumpableObject dobj; + char *rolname; + Oid srvfdw; + char *srvtype; + char *srvversion; + char *srvacl; + char *rsrvacl; + char *initsrvacl; + char *initrsrvacl; + char *srvoptions; +} ForeignServerInfo; + +typedef struct _defaultACLInfo +{ + DumpableObject dobj; + char *defaclrole; + char defaclobjtype; + char *defaclacl; + char *rdefaclacl; + char *initdefaclacl; + char *initrdefaclacl; +} DefaultACLInfo; + +typedef struct _blobInfo +{ + DumpableObject dobj; + char *rolname; + char *blobacl; + char *rblobacl; + char *initblobacl; + char *initrblobacl; +} BlobInfo; + +/* + * The PolicyInfo struct is used to represent policies on a table and + * to indicate if a table has RLS enabled (ENABLE ROW SECURITY). If + * polname is NULL, then the record indicates ENABLE ROW SECURITY, while if + * it's non-NULL then this is a regular policy definition. + */ +typedef struct _policyInfo +{ + DumpableObject dobj; + TableInfo *poltable; + char *polname; /* null indicates RLS is enabled on rel */ + char polcmd; + bool polpermissive; + char *polroles; + char *polqual; + char *polwithcheck; +} PolicyInfo; + +/* + * The PublicationInfo struct is used to represent publications. + */ +typedef struct _PublicationInfo +{ + DumpableObject dobj; + char *rolname; + bool puballtables; + bool pubinsert; + bool pubupdate; + bool pubdelete; + bool pubtruncate; + bool pubviaroot; +} PublicationInfo; + +/* + * The PublicationRelInfo struct is used to represent publication table + * mapping. + */ +typedef struct _PublicationRelInfo +{ + DumpableObject dobj; + PublicationInfo *publication; + TableInfo *pubtable; +} PublicationRelInfo; + +/* + * The SubscriptionInfo struct is used to represent subscription. + */ +typedef struct _SubscriptionInfo +{ + DumpableObject dobj; + char *rolname; + char *subconninfo; + char *subslotname; + char *subbinary; + char *substream; + char *subsynccommit; + char *subpublications; +} SubscriptionInfo; + +/* + * We build an array of these with an entry for each object that is an + * extension member according to pg_depend. + */ +typedef struct _extensionMemberId +{ + CatalogId catId; /* tableoid+oid of some member object */ + ExtensionInfo *ext; /* owning extension */ +} ExtensionMemberId; + +/* + * common utility functions + */ + +extern TableInfo *getSchemaData(Archive *fout, int *numTablesPtr); + +extern void AssignDumpId(DumpableObject *dobj); +extern DumpId createDumpId(void); +extern DumpId getMaxDumpId(void); +extern DumpableObject *findObjectByDumpId(DumpId dumpId); +extern DumpableObject *findObjectByCatalogId(CatalogId catalogId); +extern void getDumpableObjects(DumpableObject ***objs, int *numObjs); + +extern void addObjectDependency(DumpableObject *dobj, DumpId refId); +extern void removeObjectDependency(DumpableObject *dobj, DumpId refId); + +extern TableInfo *findTableByOid(Oid oid); +extern TypeInfo *findTypeByOid(Oid oid); +extern FuncInfo *findFuncByOid(Oid oid); +extern OprInfo *findOprByOid(Oid oid); +extern CollInfo *findCollationByOid(Oid oid); +extern NamespaceInfo *findNamespaceByOid(Oid oid); +extern ExtensionInfo *findExtensionByOid(Oid oid); +extern PublicationInfo *findPublicationByOid(Oid oid); + +extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems); +extern ExtensionInfo *findOwningExtension(CatalogId catalogId); + +extern void parseOidArray(const char *str, Oid *array, int arraysize); + +extern void sortDumpableObjects(DumpableObject **objs, int numObjs, + DumpId preBoundaryId, DumpId postBoundaryId); +extern void sortDumpableObjectsByTypeName(DumpableObject **objs, int numObjs); + +/* + * version specific routines + */ +extern NamespaceInfo *getNamespaces(Archive *fout, int *numNamespaces); +extern ExtensionInfo *getExtensions(Archive *fout, int *numExtensions); +extern TypeInfo *getTypes(Archive *fout, int *numTypes); +extern FuncInfo *getFuncs(Archive *fout, int *numFuncs); +extern AggInfo *getAggregates(Archive *fout, int *numAggregates); +extern OprInfo *getOperators(Archive *fout, int *numOperators); +extern AccessMethodInfo *getAccessMethods(Archive *fout, int *numAccessMethods); +extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses); +extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies); +extern CollInfo *getCollations(Archive *fout, int *numCollations); +extern ConvInfo *getConversions(Archive *fout, int *numConversions); +extern TableInfo *getTables(Archive *fout, int *numTables); +extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables); +extern InhInfo *getInherits(Archive *fout, int *numInherits); +extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables); +extern void getExtendedStatistics(Archive *fout); +extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables); +extern RuleInfo *getRules(Archive *fout, int *numRules); +extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables); +extern ProcLangInfo *getProcLangs(Archive *fout, int *numProcLangs); +extern CastInfo *getCasts(Archive *fout, int *numCasts); +extern TransformInfo *getTransforms(Archive *fout, int *numTransforms); +extern void getTableAttrs(Archive *fout, TableInfo *tbinfo, int numTables); +extern bool shouldPrintColumn(const DumpOptions *dopt, const TableInfo *tbinfo, int colno); +extern TSParserInfo *getTSParsers(Archive *fout, int *numTSParsers); +extern TSDictInfo *getTSDictionaries(Archive *fout, int *numTSDicts); +extern TSTemplateInfo *getTSTemplates(Archive *fout, int *numTSTemplates); +extern TSConfigInfo *getTSConfigurations(Archive *fout, int *numTSConfigs); +extern FdwInfo *getForeignDataWrappers(Archive *fout, + int *numForeignDataWrappers); +extern ForeignServerInfo *getForeignServers(Archive *fout, + int *numForeignServers); +extern DefaultACLInfo *getDefaultACLs(Archive *fout, int *numDefaultACLs); +extern void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[], + int numExtensions); +extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], + int numExtensions); +extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers); +extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables); +extern PublicationInfo *getPublications(Archive *fout, + int *numPublications); +extern void getPublicationTables(Archive *fout, TableInfo tblinfo[], + int numTables); +extern void getSubscriptions(Archive *fout); + +#endif /* PG_DUMP_H */ diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c new file mode 100644 index 0000000..48b5a2a --- /dev/null +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -0,0 +1,1510 @@ +/*------------------------------------------------------------------------- + * + * pg_dump_sort.c + * Sort the items of a dump into a safe order for dumping + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_dump_sort.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "catalog/pg_class_d.h" +#include "pg_backup_archiver.h" +#include "pg_backup_utils.h" +#include "pg_dump.h" + +/* + * Sort priority for database object types. + * Objects are sorted by type, and within a type by name. + * + * Triggers, event triggers, and materialized views are intentionally sorted + * late. Triggers must be restored after all data modifications, so that + * they don't interfere with loading data. Event triggers are restored + * next-to-last so that they don't interfere with object creations of any + * kind. Matview refreshes are last because they should execute in the + * database's normal state (e.g., they must come after all ACLs are restored; + * also, if they choose to look at system catalogs, they should see the final + * restore state). If you think to change this, see also the RestorePass + * mechanism in pg_backup_archiver.c. + * + * On the other hand, casts are intentionally sorted earlier than you might + * expect; logically they should come after functions, since they usually + * depend on those. This works around the backend's habit of recording + * views that use casts as dependent on the cast's underlying function. + * We initially sort casts first, and then any functions used by casts + * will be hoisted above the casts, and in turn views that those functions + * depend on will be hoisted above the functions. But views not used that + * way won't be hoisted. + * + * NOTE: object-type priorities must match the section assignments made in + * pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY, + * POST_DATA objects must sort after DO_POST_DATA_BOUNDARY, and DATA objects + * must sort between them. + */ + +/* This enum lists the priority levels in order */ +enum dbObjectTypePriorities +{ + PRIO_NAMESPACE = 1, + PRIO_PROCLANG, + PRIO_COLLATION, + PRIO_TRANSFORM, + PRIO_EXTENSION, + PRIO_TYPE, /* used for DO_TYPE and DO_SHELL_TYPE */ + PRIO_CAST, + PRIO_FUNC, + PRIO_AGG, + PRIO_ACCESS_METHOD, + PRIO_OPERATOR, + PRIO_OPFAMILY, /* used for DO_OPFAMILY and DO_OPCLASS */ + PRIO_CONVERSION, + PRIO_TSPARSER, + PRIO_TSTEMPLATE, + PRIO_TSDICT, + PRIO_TSCONFIG, + PRIO_FDW, + PRIO_FOREIGN_SERVER, + PRIO_TABLE, + PRIO_TABLE_ATTACH, + PRIO_DUMMY_TYPE, + PRIO_ATTRDEF, + PRIO_BLOB, + PRIO_PRE_DATA_BOUNDARY, /* boundary! */ + PRIO_TABLE_DATA, + PRIO_SEQUENCE_SET, + PRIO_BLOB_DATA, + PRIO_POST_DATA_BOUNDARY, /* boundary! */ + PRIO_CONSTRAINT, + PRIO_INDEX, + PRIO_INDEX_ATTACH, + PRIO_STATSEXT, + PRIO_RULE, + PRIO_TRIGGER, + PRIO_FK_CONSTRAINT, + PRIO_POLICY, + PRIO_PUBLICATION, + PRIO_PUBLICATION_REL, + PRIO_SUBSCRIPTION, + PRIO_DEFAULT_ACL, /* done in ACL pass */ + PRIO_EVENT_TRIGGER, /* must be next to last! */ + PRIO_REFRESH_MATVIEW /* must be last! */ +}; + +/* This table is indexed by enum DumpableObjectType */ +static const int dbObjectTypePriority[] = +{ + PRIO_NAMESPACE, /* DO_NAMESPACE */ + PRIO_EXTENSION, /* DO_EXTENSION */ + PRIO_TYPE, /* DO_TYPE */ + PRIO_TYPE, /* DO_SHELL_TYPE */ + PRIO_FUNC, /* DO_FUNC */ + PRIO_AGG, /* DO_AGG */ + PRIO_OPERATOR, /* DO_OPERATOR */ + PRIO_ACCESS_METHOD, /* DO_ACCESS_METHOD */ + PRIO_OPFAMILY, /* DO_OPCLASS */ + PRIO_OPFAMILY, /* DO_OPFAMILY */ + PRIO_COLLATION, /* DO_COLLATION */ + PRIO_CONVERSION, /* DO_CONVERSION */ + PRIO_TABLE, /* DO_TABLE */ + PRIO_TABLE_ATTACH, /* DO_TABLE_ATTACH */ + PRIO_ATTRDEF, /* DO_ATTRDEF */ + PRIO_INDEX, /* DO_INDEX */ + PRIO_INDEX_ATTACH, /* DO_INDEX_ATTACH */ + PRIO_STATSEXT, /* DO_STATSEXT */ + PRIO_RULE, /* DO_RULE */ + PRIO_TRIGGER, /* DO_TRIGGER */ + PRIO_CONSTRAINT, /* DO_CONSTRAINT */ + PRIO_FK_CONSTRAINT, /* DO_FK_CONSTRAINT */ + PRIO_PROCLANG, /* DO_PROCLANG */ + PRIO_CAST, /* DO_CAST */ + PRIO_TABLE_DATA, /* DO_TABLE_DATA */ + PRIO_SEQUENCE_SET, /* DO_SEQUENCE_SET */ + PRIO_DUMMY_TYPE, /* DO_DUMMY_TYPE */ + PRIO_TSPARSER, /* DO_TSPARSER */ + PRIO_TSDICT, /* DO_TSDICT */ + PRIO_TSTEMPLATE, /* DO_TSTEMPLATE */ + PRIO_TSCONFIG, /* DO_TSCONFIG */ + PRIO_FDW, /* DO_FDW */ + PRIO_FOREIGN_SERVER, /* DO_FOREIGN_SERVER */ + PRIO_DEFAULT_ACL, /* DO_DEFAULT_ACL */ + PRIO_TRANSFORM, /* DO_TRANSFORM */ + PRIO_BLOB, /* DO_BLOB */ + PRIO_BLOB_DATA, /* DO_BLOB_DATA */ + PRIO_PRE_DATA_BOUNDARY, /* DO_PRE_DATA_BOUNDARY */ + PRIO_POST_DATA_BOUNDARY, /* DO_POST_DATA_BOUNDARY */ + PRIO_EVENT_TRIGGER, /* DO_EVENT_TRIGGER */ + PRIO_REFRESH_MATVIEW, /* DO_REFRESH_MATVIEW */ + PRIO_POLICY, /* DO_POLICY */ + PRIO_PUBLICATION, /* DO_PUBLICATION */ + PRIO_PUBLICATION_REL, /* DO_PUBLICATION_REL */ + PRIO_SUBSCRIPTION /* DO_SUBSCRIPTION */ +}; + +StaticAssertDecl(lengthof(dbObjectTypePriority) == (DO_SUBSCRIPTION + 1), + "array length mismatch"); + +static DumpId preDataBoundId; +static DumpId postDataBoundId; + + +static int DOTypeNameCompare(const void *p1, const void *p2); +static bool TopoSort(DumpableObject **objs, + int numObjs, + DumpableObject **ordering, + int *nOrdering); +static void addHeapElement(int val, int *heap, int heapLength); +static int removeHeapElement(int *heap, int heapLength); +static void findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs); +static int findLoop(DumpableObject *obj, + DumpId startPoint, + bool *processed, + DumpId *searchFailed, + DumpableObject **workspace, + int depth); +static void repairDependencyLoop(DumpableObject **loop, + int nLoop); +static void describeDumpableObject(DumpableObject *obj, + char *buf, int bufsize); + + +/* + * Sort the given objects into a type/name-based ordering + * + * Normally this is just the starting point for the dependency-based + * ordering. + */ +void +sortDumpableObjectsByTypeName(DumpableObject **objs, int numObjs) +{ + if (numObjs > 1) + qsort((void *) objs, numObjs, sizeof(DumpableObject *), + DOTypeNameCompare); +} + +static int +DOTypeNameCompare(const void *p1, const void *p2) +{ + DumpableObject *obj1 = *(DumpableObject *const *) p1; + DumpableObject *obj2 = *(DumpableObject *const *) p2; + int cmpval; + + /* Sort by type's priority */ + cmpval = dbObjectTypePriority[obj1->objType] - + dbObjectTypePriority[obj2->objType]; + + if (cmpval != 0) + return cmpval; + + /* + * Sort by namespace. Typically, all objects of the same priority would + * either have or not have a namespace link, but there are exceptions. + * Sort NULL namespace after non-NULL in such cases. + */ + if (obj1->namespace) + { + if (obj2->namespace) + { + cmpval = strcmp(obj1->namespace->dobj.name, + obj2->namespace->dobj.name); + if (cmpval != 0) + return cmpval; + } + else + return -1; + } + else if (obj2->namespace) + return 1; + + /* Sort by name */ + cmpval = strcmp(obj1->name, obj2->name); + if (cmpval != 0) + return cmpval; + + /* To have a stable sort order, break ties for some object types */ + if (obj1->objType == DO_FUNC || obj1->objType == DO_AGG) + { + FuncInfo *fobj1 = *(FuncInfo *const *) p1; + FuncInfo *fobj2 = *(FuncInfo *const *) p2; + int i; + + /* Sort by number of arguments, then argument type names */ + cmpval = fobj1->nargs - fobj2->nargs; + if (cmpval != 0) + return cmpval; + for (i = 0; i < fobj1->nargs; i++) + { + TypeInfo *argtype1 = findTypeByOid(fobj1->argtypes[i]); + TypeInfo *argtype2 = findTypeByOid(fobj2->argtypes[i]); + + if (argtype1 && argtype2) + { + if (argtype1->dobj.namespace && argtype2->dobj.namespace) + { + cmpval = strcmp(argtype1->dobj.namespace->dobj.name, + argtype2->dobj.namespace->dobj.name); + if (cmpval != 0) + return cmpval; + } + cmpval = strcmp(argtype1->dobj.name, argtype2->dobj.name); + if (cmpval != 0) + return cmpval; + } + } + } + else if (obj1->objType == DO_OPERATOR) + { + OprInfo *oobj1 = *(OprInfo *const *) p1; + OprInfo *oobj2 = *(OprInfo *const *) p2; + + /* oprkind is 'l', 'r', or 'b'; this sorts prefix, postfix, infix */ + cmpval = (oobj2->oprkind - oobj1->oprkind); + if (cmpval != 0) + return cmpval; + } + else if (obj1->objType == DO_ATTRDEF) + { + AttrDefInfo *adobj1 = *(AttrDefInfo *const *) p1; + AttrDefInfo *adobj2 = *(AttrDefInfo *const *) p2; + + /* Sort by attribute number */ + cmpval = (adobj1->adnum - adobj2->adnum); + if (cmpval != 0) + return cmpval; + } + else if (obj1->objType == DO_POLICY) + { + PolicyInfo *pobj1 = *(PolicyInfo *const *) p1; + PolicyInfo *pobj2 = *(PolicyInfo *const *) p2; + + /* Sort by table name (table namespace was considered already) */ + cmpval = strcmp(pobj1->poltable->dobj.name, + pobj2->poltable->dobj.name); + if (cmpval != 0) + return cmpval; + } + else if (obj1->objType == DO_TRIGGER) + { + TriggerInfo *tobj1 = *(TriggerInfo *const *) p1; + TriggerInfo *tobj2 = *(TriggerInfo *const *) p2; + + /* Sort by table name (table namespace was considered already) */ + cmpval = strcmp(tobj1->tgtable->dobj.name, + tobj2->tgtable->dobj.name); + if (cmpval != 0) + return cmpval; + } + + /* Usually shouldn't get here, but if we do, sort by OID */ + return oidcmp(obj1->catId.oid, obj2->catId.oid); +} + + +/* + * Sort the given objects into a safe dump order using dependency + * information (to the extent we have it available). + * + * The DumpIds of the PRE_DATA_BOUNDARY and POST_DATA_BOUNDARY objects are + * passed in separately, in case we need them during dependency loop repair. + */ +void +sortDumpableObjects(DumpableObject **objs, int numObjs, + DumpId preBoundaryId, DumpId postBoundaryId) +{ + DumpableObject **ordering; + int nOrdering; + + if (numObjs <= 0) /* can't happen anymore ... */ + return; + + /* + * Saving the boundary IDs in static variables is a bit grotty, but seems + * better than adding them to parameter lists of subsidiary functions. + */ + preDataBoundId = preBoundaryId; + postDataBoundId = postBoundaryId; + + ordering = (DumpableObject **) pg_malloc(numObjs * sizeof(DumpableObject *)); + while (!TopoSort(objs, numObjs, ordering, &nOrdering)) + findDependencyLoops(ordering, nOrdering, numObjs); + + memcpy(objs, ordering, numObjs * sizeof(DumpableObject *)); + + free(ordering); +} + +/* + * TopoSort -- topological sort of a dump list + * + * Generate a re-ordering of the dump list that satisfies all the dependency + * constraints shown in the dump list. (Each such constraint is a fact of a + * partial ordering.) Minimize rearrangement of the list not needed to + * achieve the partial ordering. + * + * The input is the list of numObjs objects in objs[]. This list is not + * modified. + * + * Returns true if able to build an ordering that satisfies all the + * constraints, false if not (there are contradictory constraints). + * + * On success (true result), ordering[] is filled with a sorted array of + * DumpableObject pointers, of length equal to the input list length. + * + * On failure (false result), ordering[] is filled with an unsorted array of + * DumpableObject pointers of length *nOrdering, listing the objects that + * prevented the sort from being completed. In general, these objects either + * participate directly in a dependency cycle, or are depended on by objects + * that are in a cycle. (The latter objects are not actually problematic, + * but it takes further analysis to identify which are which.) + * + * The caller is responsible for allocating sufficient space at *ordering. + */ +static bool +TopoSort(DumpableObject **objs, + int numObjs, + DumpableObject **ordering, /* output argument */ + int *nOrdering) /* output argument */ +{ + DumpId maxDumpId = getMaxDumpId(); + int *pendingHeap; + int *beforeConstraints; + int *idMap; + DumpableObject *obj; + int heapLength; + int i, + j, + k; + + /* + * This is basically the same algorithm shown for topological sorting in + * Knuth's Volume 1. However, we would like to minimize unnecessary + * rearrangement of the input ordering; that is, when we have a choice of + * which item to output next, we always want to take the one highest in + * the original list. Therefore, instead of maintaining an unordered + * linked list of items-ready-to-output as Knuth does, we maintain a heap + * of their item numbers, which we can use as a priority queue. This + * turns the algorithm from O(N) to O(N log N) because each insertion or + * removal of a heap item takes O(log N) time. However, that's still + * plenty fast enough for this application. + */ + + *nOrdering = numObjs; /* for success return */ + + /* Eliminate the null case */ + if (numObjs <= 0) + return true; + + /* Create workspace for the above-described heap */ + pendingHeap = (int *) pg_malloc(numObjs * sizeof(int)); + + /* + * Scan the constraints, and for each item in the input, generate a count + * of the number of constraints that say it must be before something else. + * The count for the item with dumpId j is stored in beforeConstraints[j]. + * We also make a map showing the input-order index of the item with + * dumpId j. + */ + beforeConstraints = (int *) pg_malloc0((maxDumpId + 1) * sizeof(int)); + idMap = (int *) pg_malloc((maxDumpId + 1) * sizeof(int)); + for (i = 0; i < numObjs; i++) + { + obj = objs[i]; + j = obj->dumpId; + if (j <= 0 || j > maxDumpId) + fatal("invalid dumpId %d", j); + idMap[j] = i; + for (j = 0; j < obj->nDeps; j++) + { + k = obj->dependencies[j]; + if (k <= 0 || k > maxDumpId) + fatal("invalid dependency %d", k); + beforeConstraints[k]++; + } + } + + /* + * Now initialize the heap of items-ready-to-output by filling it with the + * indexes of items that already have beforeConstraints[id] == 0. + * + * The essential property of a heap is heap[(j-1)/2] >= heap[j] for each j + * in the range 1..heapLength-1 (note we are using 0-based subscripts + * here, while the discussion in Knuth assumes 1-based subscripts). So, if + * we simply enter the indexes into pendingHeap[] in decreasing order, we + * a-fortiori have the heap invariant satisfied at completion of this + * loop, and don't need to do any sift-up comparisons. + */ + heapLength = 0; + for (i = numObjs; --i >= 0;) + { + if (beforeConstraints[objs[i]->dumpId] == 0) + pendingHeap[heapLength++] = i; + } + + /*-------------------- + * Now emit objects, working backwards in the output list. At each step, + * we use the priority heap to select the last item that has no remaining + * before-constraints. We remove that item from the heap, output it to + * ordering[], and decrease the beforeConstraints count of each of the + * items it was constrained against. Whenever an item's beforeConstraints + * count is thereby decreased to zero, we insert it into the priority heap + * to show that it is a candidate to output. We are done when the heap + * becomes empty; if we have output every element then we succeeded, + * otherwise we failed. + * i = number of ordering[] entries left to output + * j = objs[] index of item we are outputting + * k = temp for scanning constraint list for item j + *-------------------- + */ + i = numObjs; + while (heapLength > 0) + { + /* Select object to output by removing largest heap member */ + j = removeHeapElement(pendingHeap, heapLength--); + obj = objs[j]; + /* Output candidate to ordering[] */ + ordering[--i] = obj; + /* Update beforeConstraints counts of its predecessors */ + for (k = 0; k < obj->nDeps; k++) + { + int id = obj->dependencies[k]; + + if ((--beforeConstraints[id]) == 0) + addHeapElement(idMap[id], pendingHeap, heapLength++); + } + } + + /* + * If we failed, report the objects that couldn't be output; these are the + * ones with beforeConstraints[] still nonzero. + */ + if (i != 0) + { + k = 0; + for (j = 1; j <= maxDumpId; j++) + { + if (beforeConstraints[j] != 0) + ordering[k++] = objs[idMap[j]]; + } + *nOrdering = k; + } + + /* Done */ + free(pendingHeap); + free(beforeConstraints); + free(idMap); + + return (i == 0); +} + +/* + * Add an item to a heap (priority queue) + * + * heapLength is the current heap size; caller is responsible for increasing + * its value after the call. There must be sufficient storage at *heap. + */ +static void +addHeapElement(int val, int *heap, int heapLength) +{ + int j; + + /* + * Sift-up the new entry, per Knuth 5.2.3 exercise 16. Note that Knuth is + * using 1-based array indexes, not 0-based. + */ + j = heapLength; + while (j > 0) + { + int i = (j - 1) >> 1; + + if (val <= heap[i]) + break; + heap[j] = heap[i]; + j = i; + } + heap[j] = val; +} + +/* + * Remove the largest item present in a heap (priority queue) + * + * heapLength is the current heap size; caller is responsible for decreasing + * its value after the call. + * + * We remove and return heap[0], which is always the largest element of + * the heap, and then "sift up" to maintain the heap invariant. + */ +static int +removeHeapElement(int *heap, int heapLength) +{ + int result = heap[0]; + int val; + int i; + + if (--heapLength <= 0) + return result; + val = heap[heapLength]; /* value that must be reinserted */ + i = 0; /* i is where the "hole" is */ + for (;;) + { + int j = 2 * i + 1; + + if (j >= heapLength) + break; + if (j + 1 < heapLength && + heap[j] < heap[j + 1]) + j++; + if (val >= heap[j]) + break; + heap[i] = heap[j]; + i = j; + } + heap[i] = val; + return result; +} + +/* + * findDependencyLoops - identify loops in TopoSort's failure output, + * and pass each such loop to repairDependencyLoop() for action + * + * In general there may be many loops in the set of objects returned by + * TopoSort; for speed we should try to repair as many loops as we can + * before trying TopoSort again. We can safely repair loops that are + * disjoint (have no members in common); if we find overlapping loops + * then we repair only the first one found, because the action taken to + * repair the first might have repaired the other as well. (If not, + * we'll fix it on the next go-round.) + * + * objs[] lists the objects TopoSort couldn't sort + * nObjs is the number of such objects + * totObjs is the total number of objects in the universe + */ +static void +findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs) +{ + /* + * We use three data structures here: + * + * processed[] is a bool array indexed by dump ID, marking the objects + * already processed during this invocation of findDependencyLoops(). + * + * searchFailed[] is another array indexed by dump ID. searchFailed[j] is + * set to dump ID k if we have proven that there is no dependency path + * leading from object j back to start point k. This allows us to skip + * useless searching when there are multiple dependency paths from k to j, + * which is a common situation. We could use a simple bool array for + * this, but then we'd need to re-zero it for each start point, resulting + * in O(N^2) zeroing work. Using the start point's dump ID as the "true" + * value lets us skip clearing the array before we consider the next start + * point. + * + * workspace[] is an array of DumpableObject pointers, in which we try to + * build lists of objects constituting loops. We make workspace[] large + * enough to hold all the objects in TopoSort's output, which is huge + * overkill in most cases but could theoretically be necessary if there is + * a single dependency chain linking all the objects. + */ + bool *processed; + DumpId *searchFailed; + DumpableObject **workspace; + bool fixedloop; + int i; + + processed = (bool *) pg_malloc0((getMaxDumpId() + 1) * sizeof(bool)); + searchFailed = (DumpId *) pg_malloc0((getMaxDumpId() + 1) * sizeof(DumpId)); + workspace = (DumpableObject **) pg_malloc(totObjs * sizeof(DumpableObject *)); + fixedloop = false; + + for (i = 0; i < nObjs; i++) + { + DumpableObject *obj = objs[i]; + int looplen; + int j; + + looplen = findLoop(obj, + obj->dumpId, + processed, + searchFailed, + workspace, + 0); + + if (looplen > 0) + { + /* Found a loop, repair it */ + repairDependencyLoop(workspace, looplen); + fixedloop = true; + /* Mark loop members as processed */ + for (j = 0; j < looplen; j++) + processed[workspace[j]->dumpId] = true; + } + else + { + /* + * There's no loop starting at this object, but mark it processed + * anyway. This is not necessary for correctness, but saves later + * invocations of findLoop() from uselessly chasing references to + * such an object. + */ + processed[obj->dumpId] = true; + } + } + + /* We'd better have fixed at least one loop */ + if (!fixedloop) + fatal("could not identify dependency loop"); + + free(workspace); + free(searchFailed); + free(processed); +} + +/* + * Recursively search for a circular dependency loop that doesn't include + * any already-processed objects. + * + * obj: object we are examining now + * startPoint: dumpId of starting object for the hoped-for circular loop + * processed[]: flag array marking already-processed objects + * searchFailed[]: flag array marking already-unsuccessfully-visited objects + * workspace[]: work array in which we are building list of loop members + * depth: number of valid entries in workspace[] at call + * + * On success, the length of the loop is returned, and workspace[] is filled + * with pointers to the members of the loop. On failure, we return 0. + * + * Note: it is possible that the given starting object is a member of more + * than one cycle; if so, we will find an arbitrary one of the cycles. + */ +static int +findLoop(DumpableObject *obj, + DumpId startPoint, + bool *processed, + DumpId *searchFailed, + DumpableObject **workspace, + int depth) +{ + int i; + + /* + * Reject if obj is already processed. This test prevents us from finding + * loops that overlap previously-processed loops. + */ + if (processed[obj->dumpId]) + return 0; + + /* + * If we've already proven there is no path from this object back to the + * startPoint, forget it. + */ + if (searchFailed[obj->dumpId] == startPoint) + return 0; + + /* + * Reject if obj is already present in workspace. This test prevents us + * from going into infinite recursion if we are given a startPoint object + * that links to a cycle it's not a member of, and it guarantees that we + * can't overflow the allocated size of workspace[]. + */ + for (i = 0; i < depth; i++) + { + if (workspace[i] == obj) + return 0; + } + + /* + * Okay, tentatively add obj to workspace + */ + workspace[depth++] = obj; + + /* + * See if we've found a loop back to the desired startPoint; if so, done + */ + for (i = 0; i < obj->nDeps; i++) + { + if (obj->dependencies[i] == startPoint) + return depth; + } + + /* + * Recurse down each outgoing branch + */ + for (i = 0; i < obj->nDeps; i++) + { + DumpableObject *nextobj = findObjectByDumpId(obj->dependencies[i]); + int newDepth; + + if (!nextobj) + continue; /* ignore dependencies on undumped objects */ + newDepth = findLoop(nextobj, + startPoint, + processed, + searchFailed, + workspace, + depth); + if (newDepth > 0) + return newDepth; + } + + /* + * Remember there is no path from here back to startPoint + */ + searchFailed[obj->dumpId] = startPoint; + + return 0; +} + +/* + * A user-defined datatype will have a dependency loop with each of its + * I/O functions (since those have the datatype as input or output). + * Similarly, a range type will have a loop with its canonicalize function, + * if any. Break the loop by making the function depend on the associated + * shell type, instead. + */ +static void +repairTypeFuncLoop(DumpableObject *typeobj, DumpableObject *funcobj) +{ + TypeInfo *typeInfo = (TypeInfo *) typeobj; + + /* remove function's dependency on type */ + removeObjectDependency(funcobj, typeobj->dumpId); + + /* add function's dependency on shell type, instead */ + if (typeInfo->shellType) + { + addObjectDependency(funcobj, typeInfo->shellType->dobj.dumpId); + + /* + * Mark shell type (always including the definition, as we need the + * shell type defined to identify the function fully) as to be dumped + * if any such function is + */ + if (funcobj->dump) + typeInfo->shellType->dobj.dump = funcobj->dump | + DUMP_COMPONENT_DEFINITION; + } +} + +/* + * Because we force a view to depend on its ON SELECT rule, while there + * will be an implicit dependency in the other direction, we need to break + * the loop. If there are no other objects in the loop then we can remove + * the implicit dependency and leave the ON SELECT rule non-separate. + * This applies to matviews, as well. + */ +static void +repairViewRuleLoop(DumpableObject *viewobj, + DumpableObject *ruleobj) +{ + /* remove rule's dependency on view */ + removeObjectDependency(ruleobj, viewobj->dumpId); + /* flags on the two objects are already set correctly for this case */ +} + +/* + * However, if there are other objects in the loop, we must break the loop + * by making the ON SELECT rule a separately-dumped object. + * + * Because findLoop() finds shorter cycles before longer ones, it's likely + * that we will have previously fired repairViewRuleLoop() and removed the + * rule's dependency on the view. Put it back to ensure the rule won't be + * emitted before the view. + * + * Note: this approach does *not* work for matviews, at the moment. + */ +static void +repairViewRuleMultiLoop(DumpableObject *viewobj, + DumpableObject *ruleobj) +{ + TableInfo *viewinfo = (TableInfo *) viewobj; + RuleInfo *ruleinfo = (RuleInfo *) ruleobj; + + /* remove view's dependency on rule */ + removeObjectDependency(viewobj, ruleobj->dumpId); + /* mark view to be printed with a dummy definition */ + viewinfo->dummy_view = true; + /* mark rule as needing its own dump */ + ruleinfo->separate = true; + /* put back rule's dependency on view */ + addObjectDependency(ruleobj, viewobj->dumpId); + /* now that rule is separate, it must be post-data */ + addObjectDependency(ruleobj, postDataBoundId); +} + +/* + * If a matview is involved in a multi-object loop, we can't currently fix + * that by splitting off the rule. As a stopgap, we try to fix it by + * dropping the constraint that the matview be dumped in the pre-data section. + * This is sufficient to handle cases where a matview depends on some unique + * index, as can happen if it has a GROUP BY for example. + * + * Note that the "next object" is not necessarily the matview itself; + * it could be the matview's rowtype, for example. We may come through here + * several times while removing all the pre-data linkages. In particular, + * if there are other matviews that depend on the one with the circularity + * problem, we'll come through here for each such matview and mark them all + * as postponed. (This works because all MVs have pre-data dependencies + * to begin with, so each of them will get visited.) + */ +static void +repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj, + DumpableObject *nextobj) +{ + /* remove boundary's dependency on object after it in loop */ + removeObjectDependency(boundaryobj, nextobj->dumpId); + /* if that object is a matview, mark it as postponed into post-data */ + if (nextobj->objType == DO_TABLE) + { + TableInfo *nextinfo = (TableInfo *) nextobj; + + if (nextinfo->relkind == RELKIND_MATVIEW) + nextinfo->postponed_def = true; + } +} + +/* + * Because we make tables depend on their CHECK constraints, while there + * will be an automatic dependency in the other direction, we need to break + * the loop. If there are no other objects in the loop then we can remove + * the automatic dependency and leave the CHECK constraint non-separate. + */ +static void +repairTableConstraintLoop(DumpableObject *tableobj, + DumpableObject *constraintobj) +{ + /* remove constraint's dependency on table */ + removeObjectDependency(constraintobj, tableobj->dumpId); +} + +/* + * However, if there are other objects in the loop, we must break the loop + * by making the CHECK constraint a separately-dumped object. + * + * Because findLoop() finds shorter cycles before longer ones, it's likely + * that we will have previously fired repairTableConstraintLoop() and + * removed the constraint's dependency on the table. Put it back to ensure + * the constraint won't be emitted before the table... + */ +static void +repairTableConstraintMultiLoop(DumpableObject *tableobj, + DumpableObject *constraintobj) +{ + /* remove table's dependency on constraint */ + removeObjectDependency(tableobj, constraintobj->dumpId); + /* mark constraint as needing its own dump */ + ((ConstraintInfo *) constraintobj)->separate = true; + /* put back constraint's dependency on table */ + addObjectDependency(constraintobj, tableobj->dumpId); + /* now that constraint is separate, it must be post-data */ + addObjectDependency(constraintobj, postDataBoundId); +} + +/* + * Attribute defaults behave exactly the same as CHECK constraints... + */ +static void +repairTableAttrDefLoop(DumpableObject *tableobj, + DumpableObject *attrdefobj) +{ + /* remove attrdef's dependency on table */ + removeObjectDependency(attrdefobj, tableobj->dumpId); +} + +static void +repairTableAttrDefMultiLoop(DumpableObject *tableobj, + DumpableObject *attrdefobj) +{ + /* remove table's dependency on attrdef */ + removeObjectDependency(tableobj, attrdefobj->dumpId); + /* mark attrdef as needing its own dump */ + ((AttrDefInfo *) attrdefobj)->separate = true; + /* put back attrdef's dependency on table */ + addObjectDependency(attrdefobj, tableobj->dumpId); +} + +/* + * CHECK constraints on domains work just like those on tables ... + */ +static void +repairDomainConstraintLoop(DumpableObject *domainobj, + DumpableObject *constraintobj) +{ + /* remove constraint's dependency on domain */ + removeObjectDependency(constraintobj, domainobj->dumpId); +} + +static void +repairDomainConstraintMultiLoop(DumpableObject *domainobj, + DumpableObject *constraintobj) +{ + /* remove domain's dependency on constraint */ + removeObjectDependency(domainobj, constraintobj->dumpId); + /* mark constraint as needing its own dump */ + ((ConstraintInfo *) constraintobj)->separate = true; + /* put back constraint's dependency on domain */ + addObjectDependency(constraintobj, domainobj->dumpId); + /* now that constraint is separate, it must be post-data */ + addObjectDependency(constraintobj, postDataBoundId); +} + +static void +repairIndexLoop(DumpableObject *partedindex, + DumpableObject *partindex) +{ + removeObjectDependency(partedindex, partindex->dumpId); +} + +/* + * Fix a dependency loop, or die trying ... + * + * This routine is mainly concerned with reducing the multiple ways that + * a loop might appear to common cases, which it passes off to the + * "fixer" routines above. + */ +static void +repairDependencyLoop(DumpableObject **loop, + int nLoop) +{ + int i, + j; + + /* Datatype and one of its I/O or canonicalize functions */ + if (nLoop == 2 && + loop[0]->objType == DO_TYPE && + loop[1]->objType == DO_FUNC) + { + repairTypeFuncLoop(loop[0], loop[1]); + return; + } + if (nLoop == 2 && + loop[1]->objType == DO_TYPE && + loop[0]->objType == DO_FUNC) + { + repairTypeFuncLoop(loop[1], loop[0]); + return; + } + + /* View (including matview) and its ON SELECT rule */ + if (nLoop == 2 && + loop[0]->objType == DO_TABLE && + loop[1]->objType == DO_RULE && + (((TableInfo *) loop[0])->relkind == RELKIND_VIEW || + ((TableInfo *) loop[0])->relkind == RELKIND_MATVIEW) && + ((RuleInfo *) loop[1])->ev_type == '1' && + ((RuleInfo *) loop[1])->is_instead && + ((RuleInfo *) loop[1])->ruletable == (TableInfo *) loop[0]) + { + repairViewRuleLoop(loop[0], loop[1]); + return; + } + if (nLoop == 2 && + loop[1]->objType == DO_TABLE && + loop[0]->objType == DO_RULE && + (((TableInfo *) loop[1])->relkind == RELKIND_VIEW || + ((TableInfo *) loop[1])->relkind == RELKIND_MATVIEW) && + ((RuleInfo *) loop[0])->ev_type == '1' && + ((RuleInfo *) loop[0])->is_instead && + ((RuleInfo *) loop[0])->ruletable == (TableInfo *) loop[1]) + { + repairViewRuleLoop(loop[1], loop[0]); + return; + } + + /* Indirect loop involving view (but not matview) and ON SELECT rule */ + if (nLoop > 2) + { + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType == DO_TABLE && + ((TableInfo *) loop[i])->relkind == RELKIND_VIEW) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_RULE && + ((RuleInfo *) loop[j])->ev_type == '1' && + ((RuleInfo *) loop[j])->is_instead && + ((RuleInfo *) loop[j])->ruletable == (TableInfo *) loop[i]) + { + repairViewRuleMultiLoop(loop[i], loop[j]); + return; + } + } + } + } + } + + /* Indirect loop involving matview and data boundary */ + if (nLoop > 2) + { + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType == DO_TABLE && + ((TableInfo *) loop[i])->relkind == RELKIND_MATVIEW) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_PRE_DATA_BOUNDARY) + { + DumpableObject *nextobj; + + nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0]; + repairMatViewBoundaryMultiLoop(loop[j], nextobj); + return; + } + } + } + } + } + + /* Table and CHECK constraint */ + if (nLoop == 2 && + loop[0]->objType == DO_TABLE && + loop[1]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[1])->contype == 'c' && + ((ConstraintInfo *) loop[1])->contable == (TableInfo *) loop[0]) + { + repairTableConstraintLoop(loop[0], loop[1]); + return; + } + if (nLoop == 2 && + loop[1]->objType == DO_TABLE && + loop[0]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[0])->contype == 'c' && + ((ConstraintInfo *) loop[0])->contable == (TableInfo *) loop[1]) + { + repairTableConstraintLoop(loop[1], loop[0]); + return; + } + + /* Indirect loop involving table and CHECK constraint */ + if (nLoop > 2) + { + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType == DO_TABLE) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[j])->contype == 'c' && + ((ConstraintInfo *) loop[j])->contable == (TableInfo *) loop[i]) + { + repairTableConstraintMultiLoop(loop[i], loop[j]); + return; + } + } + } + } + } + + /* Table and attribute default */ + if (nLoop == 2 && + loop[0]->objType == DO_TABLE && + loop[1]->objType == DO_ATTRDEF && + ((AttrDefInfo *) loop[1])->adtable == (TableInfo *) loop[0]) + { + repairTableAttrDefLoop(loop[0], loop[1]); + return; + } + if (nLoop == 2 && + loop[1]->objType == DO_TABLE && + loop[0]->objType == DO_ATTRDEF && + ((AttrDefInfo *) loop[0])->adtable == (TableInfo *) loop[1]) + { + repairTableAttrDefLoop(loop[1], loop[0]); + return; + } + + /* index on partitioned table and corresponding index on partition */ + if (nLoop == 2 && + loop[0]->objType == DO_INDEX && + loop[1]->objType == DO_INDEX) + { + if (((IndxInfo *) loop[0])->parentidx == loop[1]->catId.oid) + { + repairIndexLoop(loop[0], loop[1]); + return; + } + else if (((IndxInfo *) loop[1])->parentidx == loop[0]->catId.oid) + { + repairIndexLoop(loop[1], loop[0]); + return; + } + } + + /* Indirect loop involving table and attribute default */ + if (nLoop > 2) + { + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType == DO_TABLE) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_ATTRDEF && + ((AttrDefInfo *) loop[j])->adtable == (TableInfo *) loop[i]) + { + repairTableAttrDefMultiLoop(loop[i], loop[j]); + return; + } + } + } + } + } + + /* Domain and CHECK constraint */ + if (nLoop == 2 && + loop[0]->objType == DO_TYPE && + loop[1]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[1])->contype == 'c' && + ((ConstraintInfo *) loop[1])->condomain == (TypeInfo *) loop[0]) + { + repairDomainConstraintLoop(loop[0], loop[1]); + return; + } + if (nLoop == 2 && + loop[1]->objType == DO_TYPE && + loop[0]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[0])->contype == 'c' && + ((ConstraintInfo *) loop[0])->condomain == (TypeInfo *) loop[1]) + { + repairDomainConstraintLoop(loop[1], loop[0]); + return; + } + + /* Indirect loop involving domain and CHECK constraint */ + if (nLoop > 2) + { + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType == DO_TYPE) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_CONSTRAINT && + ((ConstraintInfo *) loop[j])->contype == 'c' && + ((ConstraintInfo *) loop[j])->condomain == (TypeInfo *) loop[i]) + { + repairDomainConstraintMultiLoop(loop[i], loop[j]); + return; + } + } + } + } + } + + /* + * Loop of table with itself --- just ignore it. + * + * (Actually, what this arises from is a dependency of a table column on + * another column, which happens with generated columns; or a dependency + * of a table column on the whole table, which happens with partitioning. + * But we didn't pay attention to sub-object IDs while collecting the + * dependency data, so we can't see that here.) + */ + if (nLoop == 1) + { + if (loop[0]->objType == DO_TABLE) + { + removeObjectDependency(loop[0], loop[0]->dumpId); + return; + } + } + + /* + * If all the objects are TABLE_DATA items, what we must have is a + * circular set of foreign key constraints (or a single self-referential + * table). Print an appropriate complaint and break the loop arbitrarily. + */ + for (i = 0; i < nLoop; i++) + { + if (loop[i]->objType != DO_TABLE_DATA) + break; + } + if (i >= nLoop) + { + pg_log_warning(ngettext("there are circular foreign-key constraints on this table:", + "there are circular foreign-key constraints among these tables:", + nLoop)); + for (i = 0; i < nLoop; i++) + pg_log_generic(PG_LOG_INFO, " %s", loop[i]->name); + pg_log_generic(PG_LOG_INFO, "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints."); + pg_log_generic(PG_LOG_INFO, "Consider using a full dump instead of a --data-only dump to avoid this problem."); + if (nLoop > 1) + removeObjectDependency(loop[0], loop[1]->dumpId); + else /* must be a self-dependency */ + removeObjectDependency(loop[0], loop[0]->dumpId); + return; + } + + /* + * If we can't find a principled way to break the loop, complain and break + * it in an arbitrary fashion. + */ + pg_log_warning("could not resolve dependency loop among these items:"); + for (i = 0; i < nLoop; i++) + { + char buf[1024]; + + describeDumpableObject(loop[i], buf, sizeof(buf)); + pg_log_generic(PG_LOG_INFO, " %s", buf); + } + + if (nLoop > 1) + removeObjectDependency(loop[0], loop[1]->dumpId); + else /* must be a self-dependency */ + removeObjectDependency(loop[0], loop[0]->dumpId); +} + +/* + * Describe a dumpable object usefully for errors + * + * This should probably go somewhere else... + */ +static void +describeDumpableObject(DumpableObject *obj, char *buf, int bufsize) +{ + switch (obj->objType) + { + case DO_NAMESPACE: + snprintf(buf, bufsize, + "SCHEMA %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_EXTENSION: + snprintf(buf, bufsize, + "EXTENSION %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TYPE: + snprintf(buf, bufsize, + "TYPE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_SHELL_TYPE: + snprintf(buf, bufsize, + "SHELL TYPE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_FUNC: + snprintf(buf, bufsize, + "FUNCTION %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_AGG: + snprintf(buf, bufsize, + "AGGREGATE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_OPERATOR: + snprintf(buf, bufsize, + "OPERATOR %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_ACCESS_METHOD: + snprintf(buf, bufsize, + "ACCESS METHOD %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_OPCLASS: + snprintf(buf, bufsize, + "OPERATOR CLASS %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_OPFAMILY: + snprintf(buf, bufsize, + "OPERATOR FAMILY %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_COLLATION: + snprintf(buf, bufsize, + "COLLATION %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_CONVERSION: + snprintf(buf, bufsize, + "CONVERSION %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TABLE: + snprintf(buf, bufsize, + "TABLE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TABLE_ATTACH: + snprintf(buf, bufsize, + "TABLE ATTACH %s (ID %d)", + obj->name, obj->dumpId); + return; + case DO_ATTRDEF: + snprintf(buf, bufsize, + "ATTRDEF %s.%s (ID %d OID %u)", + ((AttrDefInfo *) obj)->adtable->dobj.name, + ((AttrDefInfo *) obj)->adtable->attnames[((AttrDefInfo *) obj)->adnum - 1], + obj->dumpId, obj->catId.oid); + return; + case DO_INDEX: + snprintf(buf, bufsize, + "INDEX %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_INDEX_ATTACH: + snprintf(buf, bufsize, + "INDEX ATTACH %s (ID %d)", + obj->name, obj->dumpId); + return; + case DO_STATSEXT: + snprintf(buf, bufsize, + "STATISTICS %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_REFRESH_MATVIEW: + snprintf(buf, bufsize, + "REFRESH MATERIALIZED VIEW %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_RULE: + snprintf(buf, bufsize, + "RULE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TRIGGER: + snprintf(buf, bufsize, + "TRIGGER %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_EVENT_TRIGGER: + snprintf(buf, bufsize, + "EVENT TRIGGER %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_CONSTRAINT: + snprintf(buf, bufsize, + "CONSTRAINT %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_FK_CONSTRAINT: + snprintf(buf, bufsize, + "FK CONSTRAINT %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_PROCLANG: + snprintf(buf, bufsize, + "PROCEDURAL LANGUAGE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_CAST: + snprintf(buf, bufsize, + "CAST %u to %u (ID %d OID %u)", + ((CastInfo *) obj)->castsource, + ((CastInfo *) obj)->casttarget, + obj->dumpId, obj->catId.oid); + return; + case DO_TRANSFORM: + snprintf(buf, bufsize, + "TRANSFORM %u lang %u (ID %d OID %u)", + ((TransformInfo *) obj)->trftype, + ((TransformInfo *) obj)->trflang, + obj->dumpId, obj->catId.oid); + return; + case DO_TABLE_DATA: + snprintf(buf, bufsize, + "TABLE DATA %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_SEQUENCE_SET: + snprintf(buf, bufsize, + "SEQUENCE SET %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_DUMMY_TYPE: + snprintf(buf, bufsize, + "DUMMY TYPE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TSPARSER: + snprintf(buf, bufsize, + "TEXT SEARCH PARSER %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TSDICT: + snprintf(buf, bufsize, + "TEXT SEARCH DICTIONARY %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TSTEMPLATE: + snprintf(buf, bufsize, + "TEXT SEARCH TEMPLATE %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_TSCONFIG: + snprintf(buf, bufsize, + "TEXT SEARCH CONFIGURATION %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_FDW: + snprintf(buf, bufsize, + "FOREIGN DATA WRAPPER %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_FOREIGN_SERVER: + snprintf(buf, bufsize, + "FOREIGN SERVER %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_DEFAULT_ACL: + snprintf(buf, bufsize, + "DEFAULT ACL %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; + case DO_BLOB: + snprintf(buf, bufsize, + "BLOB (ID %d OID %u)", + obj->dumpId, obj->catId.oid); + return; + case DO_BLOB_DATA: + snprintf(buf, bufsize, + "BLOB DATA (ID %d)", + obj->dumpId); + return; + case DO_POLICY: + snprintf(buf, bufsize, + "POLICY (ID %d OID %u)", + obj->dumpId, obj->catId.oid); + return; + case DO_PUBLICATION: + snprintf(buf, bufsize, + "PUBLICATION (ID %d OID %u)", + obj->dumpId, obj->catId.oid); + return; + case DO_PUBLICATION_REL: + snprintf(buf, bufsize, + "PUBLICATION TABLE (ID %d OID %u)", + obj->dumpId, obj->catId.oid); + return; + case DO_SUBSCRIPTION: + snprintf(buf, bufsize, + "SUBSCRIPTION (ID %d OID %u)", + obj->dumpId, obj->catId.oid); + return; + case DO_PRE_DATA_BOUNDARY: + snprintf(buf, bufsize, + "PRE-DATA BOUNDARY (ID %d)", + obj->dumpId); + return; + case DO_POST_DATA_BOUNDARY: + snprintf(buf, bufsize, + "POST-DATA BOUNDARY (ID %d)", + obj->dumpId); + return; + } + /* shouldn't get here */ + snprintf(buf, bufsize, + "object type %d (ID %d OID %u)", + (int) obj->objType, + obj->dumpId, obj->catId.oid); +} diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c new file mode 100644 index 0000000..f8ea823 --- /dev/null +++ b/src/bin/pg_dump/pg_dumpall.c @@ -0,0 +1,1944 @@ +/*------------------------------------------------------------------------- + * + * pg_dumpall.c + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * pg_dumpall forces all pg_dump output to be text, since it also outputs + * text into the same output stream. + * + * src/bin/pg_dump/pg_dumpall.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include +#include + +#include "common/connect.h" +#include "common/file_utils.h" +#include "common/logging.h" +#include "common/string.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" +#include "getopt_long.h" +#include "pg_backup.h" + +/* version string we expect back from pg_dump */ +#define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n" + + +static void help(void); + +static void dropRoles(PGconn *conn); +static void dumpRoles(PGconn *conn); +static void dumpRoleMembership(PGconn *conn); +static void dumpGroups(PGconn *conn); +static void dropTablespaces(PGconn *conn); +static void dumpTablespaces(PGconn *conn); +static void dropDBs(PGconn *conn); +static void dumpUserConfig(PGconn *conn, const char *username); +static void dumpDatabases(PGconn *conn); +static void dumpTimestamp(const char *msg); +static int runPgDump(const char *dbname, const char *create_opts); +static void buildShSecLabels(PGconn *conn, + const char *catalog_name, Oid objectId, + const char *objtype, const char *objname, + PQExpBuffer buffer); +static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport, + const char *pguser, trivalue prompt_password, bool fail_on_error); +static char *constructConnStr(const char **keywords, const char **values); +static PGresult *executeQuery(PGconn *conn, const char *query); +static void executeCommand(PGconn *conn, const char *query); +static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, + SimpleStringList *names); + +static char pg_dump_bin[MAXPGPATH]; +static const char *progname; +static PQExpBuffer pgdumpopts; +static char *connstr = ""; +static bool output_clean = false; +static bool skip_acls = false; +static bool verbose = false; +static bool dosync = true; + +static int binary_upgrade = 0; +static int column_inserts = 0; +static int disable_dollar_quoting = 0; +static int disable_triggers = 0; +static int if_exists = 0; +static int inserts = 0; +static int no_tablespaces = 0; +static int use_setsessauth = 0; +static int no_comments = 0; +static int no_publications = 0; +static int no_security_labels = 0; +static int no_subscriptions = 0; +static int no_toast_compression = 0; +static int no_unlogged_table_data = 0; +static int no_role_passwords = 0; +static int server_version; +static int load_via_partition_root = 0; +static int on_conflict_do_nothing = 0; + +static char role_catalog[10]; +#define PG_AUTHID "pg_authid" +#define PG_ROLES "pg_roles " + +static FILE *OPF; +static char *filename = NULL; + +static SimpleStringList database_exclude_patterns = {NULL, NULL}; +static SimpleStringList database_exclude_names = {NULL, NULL}; + +#define exit_nicely(code) exit(code) + +int +main(int argc, char *argv[]) +{ + static struct option long_options[] = { + {"data-only", no_argument, NULL, 'a'}, + {"clean", no_argument, NULL, 'c'}, + {"encoding", required_argument, NULL, 'E'}, + {"file", required_argument, NULL, 'f'}, + {"globals-only", no_argument, NULL, 'g'}, + {"host", required_argument, NULL, 'h'}, + {"dbname", required_argument, NULL, 'd'}, + {"database", required_argument, NULL, 'l'}, + {"no-owner", no_argument, NULL, 'O'}, + {"port", required_argument, NULL, 'p'}, + {"roles-only", no_argument, NULL, 'r'}, + {"schema-only", no_argument, NULL, 's'}, + {"superuser", required_argument, NULL, 'S'}, + {"tablespaces-only", no_argument, NULL, 't'}, + {"username", required_argument, NULL, 'U'}, + {"verbose", no_argument, NULL, 'v'}, + {"no-password", no_argument, NULL, 'w'}, + {"password", no_argument, NULL, 'W'}, + {"no-privileges", no_argument, NULL, 'x'}, + {"no-acl", no_argument, NULL, 'x'}, + + /* + * the following options don't have an equivalent short option letter + */ + {"attribute-inserts", no_argument, &column_inserts, 1}, + {"binary-upgrade", no_argument, &binary_upgrade, 1}, + {"column-inserts", no_argument, &column_inserts, 1}, + {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1}, + {"disable-triggers", no_argument, &disable_triggers, 1}, + {"exclude-database", required_argument, NULL, 6}, + {"extra-float-digits", required_argument, NULL, 5}, + {"if-exists", no_argument, &if_exists, 1}, + {"inserts", no_argument, &inserts, 1}, + {"lock-wait-timeout", required_argument, NULL, 2}, + {"no-tablespaces", no_argument, &no_tablespaces, 1}, + {"quote-all-identifiers", no_argument, "e_all_identifiers, 1}, + {"load-via-partition-root", no_argument, &load_via_partition_root, 1}, + {"role", required_argument, NULL, 3}, + {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + {"no-comments", no_argument, &no_comments, 1}, + {"no-publications", no_argument, &no_publications, 1}, + {"no-role-passwords", no_argument, &no_role_passwords, 1}, + {"no-security-labels", no_argument, &no_security_labels, 1}, + {"no-subscriptions", no_argument, &no_subscriptions, 1}, + {"no-sync", no_argument, NULL, 4}, + {"no-toast-compression", no_argument, &no_toast_compression, 1}, + {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1}, + {"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1}, + {"rows-per-insert", required_argument, NULL, 7}, + + {NULL, 0, NULL, 0} + }; + + char *pghost = NULL; + char *pgport = NULL; + char *pguser = NULL; + char *pgdb = NULL; + char *use_role = NULL; + const char *dumpencoding = NULL; + trivalue prompt_password = TRI_DEFAULT; + bool data_only = false; + bool globals_only = false; + bool roles_only = false; + bool tablespaces_only = false; + PGconn *conn; + int encoding; + const char *std_strings; + int c, + ret; + int optindex; + + pg_logging_init(argv[0]); + pg_logging_set_level(PG_LOG_WARNING); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump")); + progname = get_progname(argv[0]); + + if (argc > 1) + { + if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) + { + help(); + exit_nicely(0); + } + if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) + { + puts("pg_dumpall (PostgreSQL) " PG_VERSION); + exit_nicely(0); + } + } + + if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR, + pg_dump_bin)) < 0) + { + char full_path[MAXPGPATH]; + + if (find_my_exec(argv[0], full_path) < 0) + strlcpy(full_path, progname, sizeof(full_path)); + + if (ret == -1) + pg_log_error("The program \"%s\" is needed by %s but was not found in the\n" + "same directory as \"%s\".\n" + "Check your installation.", + "pg_dump", progname, full_path); + else + pg_log_error("The program \"%s\" was found by \"%s\"\n" + "but was not the same version as %s.\n" + "Check your installation.", + "pg_dump", full_path, progname); + exit_nicely(1); + } + + pgdumpopts = createPQExpBuffer(); + + while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1) + { + switch (c) + { + case 'a': + data_only = true; + appendPQExpBufferStr(pgdumpopts, " -a"); + break; + + case 'c': + output_clean = true; + break; + + case 'd': + connstr = pg_strdup(optarg); + break; + + case 'E': + dumpencoding = pg_strdup(optarg); + appendPQExpBufferStr(pgdumpopts, " -E "); + appendShellString(pgdumpopts, optarg); + break; + + case 'f': + filename = pg_strdup(optarg); + appendPQExpBufferStr(pgdumpopts, " -f "); + appendShellString(pgdumpopts, filename); + break; + + case 'g': + globals_only = true; + break; + + case 'h': + pghost = pg_strdup(optarg); + break; + + case 'l': + pgdb = pg_strdup(optarg); + break; + + case 'O': + appendPQExpBufferStr(pgdumpopts, " -O"); + break; + + case 'p': + pgport = pg_strdup(optarg); + break; + + case 'r': + roles_only = true; + break; + + case 's': + appendPQExpBufferStr(pgdumpopts, " -s"); + break; + + case 'S': + appendPQExpBufferStr(pgdumpopts, " -S "); + appendShellString(pgdumpopts, optarg); + break; + + case 't': + tablespaces_only = true; + break; + + case 'U': + pguser = pg_strdup(optarg); + break; + + case 'v': + verbose = true; + pg_logging_increase_verbosity(); + appendPQExpBufferStr(pgdumpopts, " -v"); + break; + + case 'w': + prompt_password = TRI_NO; + appendPQExpBufferStr(pgdumpopts, " -w"); + break; + + case 'W': + prompt_password = TRI_YES; + appendPQExpBufferStr(pgdumpopts, " -W"); + break; + + case 'x': + skip_acls = true; + appendPQExpBufferStr(pgdumpopts, " -x"); + break; + + case 0: + break; + + case 2: + appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout "); + appendShellString(pgdumpopts, optarg); + break; + + case 3: + use_role = pg_strdup(optarg); + appendPQExpBufferStr(pgdumpopts, " --role "); + appendShellString(pgdumpopts, use_role); + break; + + case 4: + dosync = false; + appendPQExpBufferStr(pgdumpopts, " --no-sync"); + break; + + case 5: + appendPQExpBufferStr(pgdumpopts, " --extra-float-digits "); + appendShellString(pgdumpopts, optarg); + break; + + case 6: + simple_string_list_append(&database_exclude_patterns, optarg); + break; + + case 7: + appendPQExpBufferStr(pgdumpopts, " --rows-per-insert "); + appendShellString(pgdumpopts, optarg); + break; + + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit_nicely(1); + } + } + + /* Complain if any arguments remain */ + if (optind < argc) + { + pg_log_error("too many command-line arguments (first is \"%s\")", + argv[optind]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + if (database_exclude_patterns.head != NULL && + (globals_only || roles_only || tablespaces_only)) + { + pg_log_error("option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + /* Make sure the user hasn't specified a mix of globals-only options */ + if (globals_only && roles_only) + { + pg_log_error("options -g/--globals-only and -r/--roles-only cannot be used together"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + if (globals_only && tablespaces_only) + { + pg_log_error("options -g/--globals-only and -t/--tablespaces-only cannot be used together"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + if (if_exists && !output_clean) + { + pg_log_error("option --if-exists requires option -c/--clean"); + exit_nicely(1); + } + + if (roles_only && tablespaces_only) + { + pg_log_error("options -r/--roles-only and -t/--tablespaces-only cannot be used together"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + /* + * If password values are not required in the dump, switch to using + * pg_roles which is equally useful, just more likely to have unrestricted + * access than pg_authid. + */ + if (no_role_passwords) + sprintf(role_catalog, "%s", PG_ROLES); + else + sprintf(role_catalog, "%s", PG_AUTHID); + + /* Add long options to the pg_dump argument list */ + if (binary_upgrade) + appendPQExpBufferStr(pgdumpopts, " --binary-upgrade"); + if (column_inserts) + appendPQExpBufferStr(pgdumpopts, " --column-inserts"); + if (disable_dollar_quoting) + appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting"); + if (disable_triggers) + appendPQExpBufferStr(pgdumpopts, " --disable-triggers"); + if (inserts) + appendPQExpBufferStr(pgdumpopts, " --inserts"); + if (no_tablespaces) + appendPQExpBufferStr(pgdumpopts, " --no-tablespaces"); + if (quote_all_identifiers) + appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers"); + if (load_via_partition_root) + appendPQExpBufferStr(pgdumpopts, " --load-via-partition-root"); + if (use_setsessauth) + appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization"); + if (no_comments) + appendPQExpBufferStr(pgdumpopts, " --no-comments"); + if (no_publications) + appendPQExpBufferStr(pgdumpopts, " --no-publications"); + if (no_security_labels) + appendPQExpBufferStr(pgdumpopts, " --no-security-labels"); + if (no_subscriptions) + appendPQExpBufferStr(pgdumpopts, " --no-subscriptions"); + if (no_toast_compression) + appendPQExpBufferStr(pgdumpopts, " --no-toast-compression"); + if (no_unlogged_table_data) + appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data"); + if (on_conflict_do_nothing) + appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing"); + + /* + * If there was a database specified on the command line, use that, + * otherwise try to connect to database "postgres", and failing that + * "template1". "postgres" is the preferred choice for 8.1 and later + * servers, but it usually will not exist on older ones. + */ + if (pgdb) + { + conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser, + prompt_password, false); + + if (!conn) + { + pg_log_error("could not connect to database \"%s\"", pgdb); + exit_nicely(1); + } + } + else + { + conn = connectDatabase("postgres", connstr, pghost, pgport, pguser, + prompt_password, false); + if (!conn) + conn = connectDatabase("template1", connstr, pghost, pgport, pguser, + prompt_password, true); + + if (!conn) + { + pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n" + "Please specify an alternative database."); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + } + + /* + * Get a list of database names that match the exclude patterns + */ + expand_dbname_patterns(conn, &database_exclude_patterns, + &database_exclude_names); + + /* + * Open the output file if required, otherwise use stdout + */ + if (filename) + { + OPF = fopen(filename, PG_BINARY_W); + if (!OPF) + { + pg_log_error("could not open output file \"%s\": %m", + filename); + exit_nicely(1); + } + } + else + OPF = stdout; + + /* + * Set the client encoding if requested. + */ + if (dumpencoding) + { + if (PQsetClientEncoding(conn, dumpencoding) < 0) + { + pg_log_error("invalid client encoding \"%s\" specified", + dumpencoding); + exit_nicely(1); + } + } + + /* + * Get the active encoding and the standard_conforming_strings setting, so + * we know how to escape strings. + */ + encoding = PQclientEncoding(conn); + std_strings = PQparameterStatus(conn, "standard_conforming_strings"); + if (!std_strings) + std_strings = "off"; + + /* Set the role if requested */ + if (use_role && server_version >= 80100) + { + PQExpBuffer query = createPQExpBuffer(); + + appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role)); + executeCommand(conn, query->data); + destroyPQExpBuffer(query); + } + + /* Force quoting of all identifiers if requested. */ + if (quote_all_identifiers && server_version >= 90100) + executeCommand(conn, "SET quote_all_identifiers = true"); + + fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n"); + if (verbose) + dumpTimestamp("Started on"); + + /* + * We used to emit \connect postgres here, but that served no purpose + * other than to break things for installations without a postgres + * database. Everything we're restoring here is a global, so whichever + * database we're connected to at the moment is fine. + */ + + /* Restore will need to write to the target cluster */ + fprintf(OPF, "SET default_transaction_read_only = off;\n\n"); + + /* Replicate encoding and std_strings in output */ + fprintf(OPF, "SET client_encoding = '%s';\n", + pg_encoding_to_char(encoding)); + fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings); + if (strcmp(std_strings, "off") == 0) + fprintf(OPF, "SET escape_string_warning = off;\n"); + fprintf(OPF, "\n"); + + if (!data_only) + { + /* + * If asked to --clean, do that first. We can avoid detailed + * dependency analysis because databases never depend on each other, + * and tablespaces never depend on each other. Roles could have + * grants to each other, but DROP ROLE will clean those up silently. + */ + if (output_clean) + { + if (!globals_only && !roles_only && !tablespaces_only) + dropDBs(conn); + + if (!roles_only && !no_tablespaces) + dropTablespaces(conn); + + if (!tablespaces_only) + dropRoles(conn); + } + + /* + * Now create objects as requested. Be careful that option logic here + * is the same as for drops above. + */ + if (!tablespaces_only) + { + /* Dump roles (users) */ + dumpRoles(conn); + + /* Dump role memberships --- need different method for pre-8.1 */ + if (server_version >= 80100) + dumpRoleMembership(conn); + else + dumpGroups(conn); + } + + /* Dump tablespaces */ + if (!roles_only && !no_tablespaces) + dumpTablespaces(conn); + } + + if (!globals_only && !roles_only && !tablespaces_only) + dumpDatabases(conn); + + PQfinish(conn); + + if (verbose) + dumpTimestamp("Completed on"); + fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n"); + + if (filename) + { + fclose(OPF); + + /* sync the resulting file, errors are not fatal */ + if (dosync) + (void) fsync_fname(filename, false); + } + + exit_nicely(0); +} + + +static void +help(void) +{ + printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]...\n"), progname); + + printf(_("\nGeneral options:\n")); + printf(_(" -f, --file=FILENAME output file name\n")); + printf(_(" -v, --verbose verbose mode\n")); + printf(_(" -V, --version output version information, then exit\n")); + printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n")); + printf(_(" -?, --help show this help, then exit\n")); + printf(_("\nOptions controlling the output content:\n")); + printf(_(" -a, --data-only dump only the data, not the schema\n")); + printf(_(" -c, --clean clean (drop) databases before recreating\n")); + printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n")); + printf(_(" -g, --globals-only dump only global objects, no databases\n")); + printf(_(" -O, --no-owner skip restoration of object ownership\n")); + printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n")); + printf(_(" -s, --schema-only dump only the schema, no data\n")); + printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n")); + printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n")); + printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n")); + printf(_(" --binary-upgrade for use by upgrade utilities only\n")); + printf(_(" --column-inserts dump data as INSERT commands with column names\n")); + printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n")); + printf(_(" --disable-triggers disable triggers during data-only restore\n")); + printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n")); + printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n")); + printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --inserts dump data as INSERT commands, rather than COPY\n")); + printf(_(" --load-via-partition-root load partitions via the root table\n")); + printf(_(" --no-comments do not dump comments\n")); + printf(_(" --no-publications do not dump publications\n")); + printf(_(" --no-role-passwords do not dump passwords for roles\n")); + printf(_(" --no-security-labels do not dump security label assignments\n")); + printf(_(" --no-subscriptions do not dump subscriptions\n")); + printf(_(" --no-sync do not wait for changes to be written safely to disk\n")); + printf(_(" --no-tablespaces do not dump tablespace assignments\n")); + printf(_(" --no-toast-compression do not dump TOAST compression methods\n")); + printf(_(" --no-unlogged-table-data do not dump unlogged table data\n")); + printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n")); + printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); + printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n")); + printf(_(" --use-set-session-authorization\n" + " use SET SESSION AUTHORIZATION commands instead of\n" + " ALTER OWNER commands to set ownership\n")); + + printf(_("\nConnection options:\n")); + printf(_(" -d, --dbname=CONNSTR connect using connection string\n")); + printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); + printf(_(" -l, --database=DBNAME alternative default database\n")); + printf(_(" -p, --port=PORT database server port number\n")); + printf(_(" -U, --username=NAME connect as specified database user\n")); + printf(_(" -w, --no-password never prompt for password\n")); + printf(_(" -W, --password force password prompt (should happen automatically)\n")); + printf(_(" --role=ROLENAME do SET ROLE before dump\n")); + + printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n" + "output.\n\n")); + printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); + printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); +} + + +/* + * Drop roles + */ +static void +dropRoles(PGconn *conn) +{ + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int i_rolname; + int i; + + if (server_version >= 90600) + printfPQExpBuffer(buf, + "SELECT rolname " + "FROM %s " + "WHERE rolname !~ '^pg_' " + "ORDER BY 1", role_catalog); + else if (server_version >= 80100) + printfPQExpBuffer(buf, + "SELECT rolname " + "FROM %s " + "ORDER BY 1", role_catalog); + else + printfPQExpBuffer(buf, + "SELECT usename as rolname " + "FROM pg_shadow " + "UNION " + "SELECT groname as rolname " + "FROM pg_group " + "ORDER BY 1"); + + res = executeQuery(conn, buf->data); + + i_rolname = PQfnumber(res, "rolname"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Drop roles\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + const char *rolename; + + rolename = PQgetvalue(res, i, i_rolname); + + fprintf(OPF, "DROP ROLE %s%s;\n", + if_exists ? "IF EXISTS " : "", + fmtId(rolename)); + } + + PQclear(res); + destroyPQExpBuffer(buf); + + fprintf(OPF, "\n\n"); +} + +/* + * Dump roles + */ +static void +dumpRoles(PGconn *conn) +{ + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int i_oid, + i_rolname, + i_rolsuper, + i_rolinherit, + i_rolcreaterole, + i_rolcreatedb, + i_rolcanlogin, + i_rolconnlimit, + i_rolpassword, + i_rolvaliduntil, + i_rolreplication, + i_rolbypassrls, + i_rolcomment, + i_is_current_user; + int i; + + /* note: rolconfig is dumped later */ + if (server_version >= 90600) + printfPQExpBuffer(buf, + "SELECT oid, rolname, rolsuper, rolinherit, " + "rolcreaterole, rolcreatedb, " + "rolcanlogin, rolconnlimit, rolpassword, " + "rolvaliduntil, rolreplication, rolbypassrls, " + "pg_catalog.shobj_description(oid, '%s') as rolcomment, " + "rolname = current_user AS is_current_user " + "FROM %s " + "WHERE rolname !~ '^pg_' " + "ORDER BY 2", role_catalog, role_catalog); + else if (server_version >= 90500) + printfPQExpBuffer(buf, + "SELECT oid, rolname, rolsuper, rolinherit, " + "rolcreaterole, rolcreatedb, " + "rolcanlogin, rolconnlimit, rolpassword, " + "rolvaliduntil, rolreplication, rolbypassrls, " + "pg_catalog.shobj_description(oid, '%s') as rolcomment, " + "rolname = current_user AS is_current_user " + "FROM %s " + "ORDER BY 2", role_catalog, role_catalog); + else if (server_version >= 90100) + printfPQExpBuffer(buf, + "SELECT oid, rolname, rolsuper, rolinherit, " + "rolcreaterole, rolcreatedb, " + "rolcanlogin, rolconnlimit, rolpassword, " + "rolvaliduntil, rolreplication, " + "false as rolbypassrls, " + "pg_catalog.shobj_description(oid, '%s') as rolcomment, " + "rolname = current_user AS is_current_user " + "FROM %s " + "ORDER BY 2", role_catalog, role_catalog); + else if (server_version >= 80200) + printfPQExpBuffer(buf, + "SELECT oid, rolname, rolsuper, rolinherit, " + "rolcreaterole, rolcreatedb, " + "rolcanlogin, rolconnlimit, rolpassword, " + "rolvaliduntil, false as rolreplication, " + "false as rolbypassrls, " + "pg_catalog.shobj_description(oid, '%s') as rolcomment, " + "rolname = current_user AS is_current_user " + "FROM %s " + "ORDER BY 2", role_catalog, role_catalog); + else if (server_version >= 80100) + printfPQExpBuffer(buf, + "SELECT oid, rolname, rolsuper, rolinherit, " + "rolcreaterole, rolcreatedb, " + "rolcanlogin, rolconnlimit, rolpassword, " + "rolvaliduntil, false as rolreplication, " + "false as rolbypassrls, " + "null as rolcomment, " + "rolname = current_user AS is_current_user " + "FROM %s " + "ORDER BY 2", role_catalog); + else + printfPQExpBuffer(buf, + "SELECT 0 as oid, usename as rolname, " + "usesuper as rolsuper, " + "true as rolinherit, " + "usesuper as rolcreaterole, " + "usecreatedb as rolcreatedb, " + "true as rolcanlogin, " + "-1 as rolconnlimit, " + "passwd as rolpassword, " + "valuntil as rolvaliduntil, " + "false as rolreplication, " + "false as rolbypassrls, " + "null as rolcomment, " + "usename = current_user AS is_current_user " + "FROM pg_shadow " + "UNION ALL " + "SELECT 0 as oid, groname as rolname, " + "false as rolsuper, " + "true as rolinherit, " + "false as rolcreaterole, " + "false as rolcreatedb, " + "false as rolcanlogin, " + "-1 as rolconnlimit, " + "null::text as rolpassword, " + "null::timestamptz as rolvaliduntil, " + "false as rolreplication, " + "false as rolbypassrls, " + "null as rolcomment, " + "false AS is_current_user " + "FROM pg_group " + "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow " + " WHERE usename = groname) " + "ORDER BY 2"); + + res = executeQuery(conn, buf->data); + + i_oid = PQfnumber(res, "oid"); + i_rolname = PQfnumber(res, "rolname"); + i_rolsuper = PQfnumber(res, "rolsuper"); + i_rolinherit = PQfnumber(res, "rolinherit"); + i_rolcreaterole = PQfnumber(res, "rolcreaterole"); + i_rolcreatedb = PQfnumber(res, "rolcreatedb"); + i_rolcanlogin = PQfnumber(res, "rolcanlogin"); + i_rolconnlimit = PQfnumber(res, "rolconnlimit"); + i_rolpassword = PQfnumber(res, "rolpassword"); + i_rolvaliduntil = PQfnumber(res, "rolvaliduntil"); + i_rolreplication = PQfnumber(res, "rolreplication"); + i_rolbypassrls = PQfnumber(res, "rolbypassrls"); + i_rolcomment = PQfnumber(res, "rolcomment"); + i_is_current_user = PQfnumber(res, "is_current_user"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Roles\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + const char *rolename; + Oid auth_oid; + + auth_oid = atooid(PQgetvalue(res, i, i_oid)); + rolename = PQgetvalue(res, i, i_rolname); + + if (strncmp(rolename, "pg_", 3) == 0) + { + pg_log_warning("role name starting with \"pg_\" skipped (%s)", + rolename); + continue; + } + + resetPQExpBuffer(buf); + + if (binary_upgrade) + { + appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n"); + appendPQExpBuffer(buf, + "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n", + auth_oid); + } + + /* + * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role + * will acquire the right properties even if it already exists (ie, it + * won't hurt for the CREATE to fail). This is particularly important + * for the role we are connected as, since even with --clean we will + * have failed to drop it. binary_upgrade cannot generate any errors, + * so we assume the current role is already created. + */ + if (!binary_upgrade || + strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0) + appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename)); + appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename)); + + if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0) + appendPQExpBufferStr(buf, " SUPERUSER"); + else + appendPQExpBufferStr(buf, " NOSUPERUSER"); + + if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0) + appendPQExpBufferStr(buf, " INHERIT"); + else + appendPQExpBufferStr(buf, " NOINHERIT"); + + if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0) + appendPQExpBufferStr(buf, " CREATEROLE"); + else + appendPQExpBufferStr(buf, " NOCREATEROLE"); + + if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0) + appendPQExpBufferStr(buf, " CREATEDB"); + else + appendPQExpBufferStr(buf, " NOCREATEDB"); + + if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0) + appendPQExpBufferStr(buf, " LOGIN"); + else + appendPQExpBufferStr(buf, " NOLOGIN"); + + if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0) + appendPQExpBufferStr(buf, " REPLICATION"); + else + appendPQExpBufferStr(buf, " NOREPLICATION"); + + if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0) + appendPQExpBufferStr(buf, " BYPASSRLS"); + else + appendPQExpBufferStr(buf, " NOBYPASSRLS"); + + if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0) + appendPQExpBuffer(buf, " CONNECTION LIMIT %s", + PQgetvalue(res, i, i_rolconnlimit)); + + + if (!PQgetisnull(res, i, i_rolpassword) && !no_role_passwords) + { + appendPQExpBufferStr(buf, " PASSWORD "); + appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn); + } + + if (!PQgetisnull(res, i, i_rolvaliduntil)) + appendPQExpBuffer(buf, " VALID UNTIL '%s'", + PQgetvalue(res, i, i_rolvaliduntil)); + + appendPQExpBufferStr(buf, ";\n"); + + if (!no_comments && !PQgetisnull(res, i, i_rolcomment)) + { + appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename)); + appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn); + appendPQExpBufferStr(buf, ";\n"); + } + + if (!no_security_labels && server_version >= 90200) + buildShSecLabels(conn, "pg_authid", auth_oid, + "ROLE", rolename, + buf); + + fprintf(OPF, "%s", buf->data); + } + + /* + * Dump configuration settings for roles after all roles have been dumped. + * We do it this way because config settings for roles could mention the + * names of other roles. + */ + for (i = 0; i < PQntuples(res); i++) + dumpUserConfig(conn, PQgetvalue(res, i, i_rolname)); + + PQclear(res); + + fprintf(OPF, "\n\n"); + + destroyPQExpBuffer(buf); +} + + +/* + * Dump role memberships. This code is used for 8.1 and later servers. + * + * Note: we expect dumpRoles already created all the roles, but there is + * no membership yet. + */ +static void +dumpRoleMembership(PGconn *conn) +{ + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int i; + + printfPQExpBuffer(buf, "SELECT ur.rolname AS roleid, " + "um.rolname AS member, " + "a.admin_option, " + "ug.rolname AS grantor " + "FROM pg_auth_members a " + "LEFT JOIN %s ur on ur.oid = a.roleid " + "LEFT JOIN %s um on um.oid = a.member " + "LEFT JOIN %s ug on ug.oid = a.grantor " + "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')" + "ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog); + res = executeQuery(conn, buf->data); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Role memberships\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + char *roleid = PQgetvalue(res, i, 0); + char *member = PQgetvalue(res, i, 1); + char *option = PQgetvalue(res, i, 2); + + fprintf(OPF, "GRANT %s", fmtId(roleid)); + fprintf(OPF, " TO %s", fmtId(member)); + if (*option == 't') + fprintf(OPF, " WITH ADMIN OPTION"); + + /* + * We don't track the grantor very carefully in the backend, so cope + * with the possibility that it has been dropped. + */ + if (!PQgetisnull(res, i, 3)) + { + char *grantor = PQgetvalue(res, i, 3); + + fprintf(OPF, " GRANTED BY %s", fmtId(grantor)); + } + fprintf(OPF, ";\n"); + } + + PQclear(res); + destroyPQExpBuffer(buf); + + fprintf(OPF, "\n\n"); +} + +/* + * Dump group memberships from a pre-8.1 server. It's annoying that we + * can't share any useful amount of code with the post-8.1 case, but + * the catalog representations are too different. + * + * Note: we expect dumpRoles already created all the roles, but there is + * no membership yet. + */ +static void +dumpGroups(PGconn *conn) +{ + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int i; + + res = executeQuery(conn, + "SELECT groname, grolist FROM pg_group ORDER BY 1"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Role memberships\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + char *groname = PQgetvalue(res, i, 0); + char *grolist = PQgetvalue(res, i, 1); + PGresult *res2; + int j; + + /* + * Array representation is {1,2,3} ... convert to (1,2,3) + */ + if (strlen(grolist) < 3) + continue; + + grolist = pg_strdup(grolist); + grolist[0] = '('; + grolist[strlen(grolist) - 1] = ')'; + printfPQExpBuffer(buf, + "SELECT usename FROM pg_shadow " + "WHERE usesysid IN %s ORDER BY 1", + grolist); + free(grolist); + + res2 = executeQuery(conn, buf->data); + + for (j = 0; j < PQntuples(res2); j++) + { + char *usename = PQgetvalue(res2, j, 0); + + /* + * Don't try to grant a role to itself; can happen if old + * installation has identically named user and group. + */ + if (strcmp(groname, usename) == 0) + continue; + + fprintf(OPF, "GRANT %s", fmtId(groname)); + fprintf(OPF, " TO %s;\n", fmtId(usename)); + } + + PQclear(res2); + } + + PQclear(res); + destroyPQExpBuffer(buf); + + fprintf(OPF, "\n\n"); +} + + +/* + * Drop tablespaces. + */ +static void +dropTablespaces(PGconn *conn) +{ + PGresult *res; + int i; + + /* + * Get all tablespaces except built-in ones (which we assume are named + * pg_xxx) + */ + res = executeQuery(conn, "SELECT spcname " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + char *spcname = PQgetvalue(res, i, 0); + + fprintf(OPF, "DROP TABLESPACE %s%s;\n", + if_exists ? "IF EXISTS " : "", + fmtId(spcname)); + } + + PQclear(res); + + fprintf(OPF, "\n\n"); +} + +/* + * Dump tablespaces. + */ +static void +dumpTablespaces(PGconn *conn) +{ + PGresult *res; + int i; + + /* + * Get all tablespaces except built-in ones (which we assume are named + * pg_xxx) + * + * For the tablespace ACLs, as of 9.6, we extract both the positive (as + * spcacl) and negative (as rspcacl) ACLs, relative to the default ACL for + * tablespaces, which are then passed to buildACLCommands() below. + * + * See buildACLQueries() and buildACLCommands(). + * + * The order in which privileges are in the ACL string (the order they + * have been GRANT'd in, which the backend maintains) must be preserved to + * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on + * those are dumped in the correct order. + * + * Note that we do not support initial privileges (pg_init_privs) on + * tablespaces, so this logic cannot make use of buildACLQueries(). + */ + if (server_version >= 90600) + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "pg_catalog.pg_tablespace_location(oid), " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " WITH ORDINALITY AS perm(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(acldefault('t',spcowner)) " + " AS init(init_acl) " + " WHERE acl = init_acl)) AS spcacls) " + " AS spcacl, " + "(SELECT array_agg(acl ORDER BY row_n) FROM " + " (SELECT acl, row_n FROM " + " unnest(acldefault('t',spcowner)) " + " WITH ORDINALITY AS initp(acl,row_n) " + " WHERE NOT EXISTS ( " + " SELECT 1 " + " FROM unnest(coalesce(spcacl,acldefault('t',spcowner))) " + " AS permp(orig_acl) " + " WHERE acl = orig_acl)) AS rspcacls) " + " AS rspcacl, " + "array_to_string(spcoptions, ', ')," + "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + else if (server_version >= 90200) + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "pg_catalog.pg_tablespace_location(oid), " + "spcacl, '' as rspcacl, " + "array_to_string(spcoptions, ', ')," + "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + else if (server_version >= 90000) + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "spclocation, spcacl, '' as rspcacl, " + "array_to_string(spcoptions, ', ')," + "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + else if (server_version >= 80200) + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "spclocation, spcacl, '' as rspcacl, null, " + "pg_catalog.shobj_description(oid, 'pg_tablespace') " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + else + res = executeQuery(conn, "SELECT oid, spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "spclocation, spcacl, '' as rspcacl, " + "null, null " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Tablespaces\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + PQExpBuffer buf = createPQExpBuffer(); + Oid spcoid = atooid(PQgetvalue(res, i, 0)); + char *spcname = PQgetvalue(res, i, 1); + char *spcowner = PQgetvalue(res, i, 2); + char *spclocation = PQgetvalue(res, i, 3); + char *spcacl = PQgetvalue(res, i, 4); + char *rspcacl = PQgetvalue(res, i, 5); + char *spcoptions = PQgetvalue(res, i, 6); + char *spccomment = PQgetvalue(res, i, 7); + char *fspcname; + + /* needed for buildACLCommands() */ + fspcname = pg_strdup(fmtId(spcname)); + + appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname); + appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner)); + + appendPQExpBufferStr(buf, " LOCATION "); + appendStringLiteralConn(buf, spclocation, conn); + appendPQExpBufferStr(buf, ";\n"); + + if (spcoptions && spcoptions[0] != '\0') + appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n", + fspcname, spcoptions); + + if (!skip_acls && + !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE", + spcacl, rspcacl, + spcowner, "", server_version, buf)) + { + pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"", + spcacl, spcname); + PQfinish(conn); + exit_nicely(1); + } + + if (!no_comments && spccomment && spccomment[0] != '\0') + { + appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname); + appendStringLiteralConn(buf, spccomment, conn); + appendPQExpBufferStr(buf, ";\n"); + } + + if (!no_security_labels && server_version >= 90200) + buildShSecLabels(conn, "pg_tablespace", spcoid, + "TABLESPACE", spcname, + buf); + + fprintf(OPF, "%s", buf->data); + + free(fspcname); + destroyPQExpBuffer(buf); + } + + PQclear(res); + fprintf(OPF, "\n\n"); +} + + +/* + * Dump commands to drop each database. + */ +static void +dropDBs(PGconn *conn) +{ + PGresult *res; + int i; + + /* + * Skip databases marked not datallowconn, since we'd be unable to connect + * to them anyway. This must agree with dumpDatabases(). + */ + res = executeQuery(conn, + "SELECT datname " + "FROM pg_database d " + "WHERE datallowconn " + "ORDER BY datname"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Drop databases (except postgres and template1)\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + char *dbname = PQgetvalue(res, i, 0); + + /* + * Skip "postgres" and "template1"; dumpDatabases() will deal with + * them specially. Also, be sure to skip "template0", even if for + * some reason it's not marked !datallowconn. + */ + if (strcmp(dbname, "template1") != 0 && + strcmp(dbname, "template0") != 0 && + strcmp(dbname, "postgres") != 0) + { + fprintf(OPF, "DROP DATABASE %s%s;\n", + if_exists ? "IF EXISTS " : "", + fmtId(dbname)); + } + } + + PQclear(res); + + fprintf(OPF, "\n\n"); +} + + +/* + * Dump user-specific configuration + */ +static void +dumpUserConfig(PGconn *conn, const char *username) +{ + PQExpBuffer buf = createPQExpBuffer(); + int count = 1; + bool first = true; + + for (;;) + { + PGresult *res; + + if (server_version >= 90000) + printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE " + "setdatabase = 0 AND setrole = " + "(SELECT oid FROM %s WHERE rolname = ", count, role_catalog); + else if (server_version >= 80100) + printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM %s WHERE rolname = ", count, role_catalog); + else + printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count); + appendStringLiteralConn(buf, username, conn); + if (server_version >= 90000) + appendPQExpBufferChar(buf, ')'); + + res = executeQuery(conn, buf->data); + if (PQntuples(res) == 1 && + !PQgetisnull(res, 0, 0)) + { + /* comment at section start, only if needed */ + if (first) + { + fprintf(OPF, "--\n-- User Configurations\n--\n\n"); + first = false; + } + + fprintf(OPF, "--\n-- User Config \"%s\"\n--\n\n", username); + resetPQExpBuffer(buf); + makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0), + "ROLE", username, NULL, NULL, + buf); + fprintf(OPF, "%s", buf->data); + PQclear(res); + count++; + } + else + { + PQclear(res); + break; + } + } + + destroyPQExpBuffer(buf); +} + +/* + * Find a list of database names that match the given patterns. + * See also expand_table_name_patterns() in pg_dump.c + */ +static void +expand_dbname_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleStringList *names) +{ + PQExpBuffer query; + PGresult *res; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * The loop below runs multiple SELECTs, which might sometimes result in + * duplicate entries in the name list, but we don't care, since all we're + * going to do is test membership of the list. + */ + + for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next) + { + int dotcnt; + + appendPQExpBufferStr(query, + "SELECT datname FROM pg_catalog.pg_database n\n"); + processSQLNamePattern(conn, query, cell->val, false, + false, NULL, "datname", NULL, NULL, NULL, + &dotcnt); + + if (dotcnt > 0) + { + pg_log_error("improper qualified name (too many dotted names): %s", + cell->val); + PQfinish(conn); + exit_nicely(1); + } + + res = executeQuery(conn, query->data); + for (int i = 0; i < PQntuples(res); i++) + { + simple_string_list_append(names, PQgetvalue(res, i, 0)); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} + +/* + * Dump contents of databases. + */ +static void +dumpDatabases(PGconn *conn) +{ + PGresult *res; + int i; + + /* + * Skip databases marked not datallowconn, since we'd be unable to connect + * to them anyway. This must agree with dropDBs(). + * + * We arrange for template1 to be processed first, then we process other + * DBs in alphabetical order. If we just did them all alphabetically, we + * might find ourselves trying to drop the "postgres" database while still + * connected to it. This makes trying to run the restore script while + * connected to "template1" a bad idea, but there's no fixed order that + * doesn't have some failure mode with --clean. + */ + res = executeQuery(conn, + "SELECT datname " + "FROM pg_database d " + "WHERE datallowconn " + "ORDER BY (datname <> 'template1'), datname"); + + if (PQntuples(res) > 0) + fprintf(OPF, "--\n-- Databases\n--\n\n"); + + for (i = 0; i < PQntuples(res); i++) + { + char *dbname = PQgetvalue(res, i, 0); + const char *create_opts; + int ret; + + /* Skip template0, even if it's not marked !datallowconn. */ + if (strcmp(dbname, "template0") == 0) + continue; + + /* Skip any explicitly excluded database */ + if (simple_string_list_member(&database_exclude_names, dbname)) + { + pg_log_info("excluding database \"%s\"", dbname); + continue; + } + + pg_log_info("dumping database \"%s\"", dbname); + + fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", dbname); + + /* + * We assume that "template1" and "postgres" already exist in the + * target installation. dropDBs() won't have removed them, for fear + * of removing the DB the restore script is initially connected to. If + * --clean was specified, tell pg_dump to drop and recreate them; + * otherwise we'll merely restore their contents. Other databases + * should simply be created. + */ + if (strcmp(dbname, "template1") == 0 || strcmp(dbname, "postgres") == 0) + { + if (output_clean) + create_opts = "--clean --create"; + else + { + create_opts = ""; + /* Since pg_dump won't emit a \connect command, we must */ + fprintf(OPF, "\\connect %s\n\n", dbname); + } + } + else + create_opts = "--create"; + + if (filename) + fclose(OPF); + + ret = runPgDump(dbname, create_opts); + if (ret != 0) + { + pg_log_error("pg_dump failed on database \"%s\", exiting", dbname); + exit_nicely(1); + } + + if (filename) + { + OPF = fopen(filename, PG_BINARY_A); + if (!OPF) + { + pg_log_error("could not re-open the output file \"%s\": %m", + filename); + exit_nicely(1); + } + } + + } + + PQclear(res); +} + + + +/* + * Run pg_dump on dbname, with specified options. + */ +static int +runPgDump(const char *dbname, const char *create_opts) +{ + PQExpBuffer connstrbuf = createPQExpBuffer(); + PQExpBuffer cmd = createPQExpBuffer(); + int ret; + + appendPQExpBuffer(cmd, "\"%s\" %s %s", pg_dump_bin, + pgdumpopts->data, create_opts); + + /* + * If we have a filename, use the undocumented plain-append pg_dump + * format. + */ + if (filename) + appendPQExpBufferStr(cmd, " -Fa "); + else + appendPQExpBufferStr(cmd, " -Fp "); + + /* + * Append the database name to the already-constructed stem of connection + * string. + */ + appendPQExpBuffer(connstrbuf, "%s dbname=", connstr); + appendConnStrVal(connstrbuf, dbname); + + appendShellString(cmd, connstrbuf->data); + + pg_log_info("running \"%s\"", cmd->data); + + fflush(stdout); + fflush(stderr); + + ret = system(cmd->data); + + destroyPQExpBuffer(cmd); + destroyPQExpBuffer(connstrbuf); + + return ret; +} + +/* + * buildShSecLabels + * + * Build SECURITY LABEL command(s) for a shared object + * + * The caller has to provide object type and identity in two separate formats: + * catalog_name (e.g., "pg_database") and object OID, as well as + * type name (e.g., "DATABASE") and object name (not pre-quoted). + * + * The command(s) are appended to "buffer". + */ +static void +buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, + const char *objtype, const char *objname, + PQExpBuffer buffer) +{ + PQExpBuffer sql = createPQExpBuffer(); + PGresult *res; + + buildShSecLabelQuery(catalog_name, objectId, sql); + res = executeQuery(conn, sql->data); + emitShSecLabels(conn, res, buffer, objtype, objname); + + PQclear(res); + destroyPQExpBuffer(sql); +} + +/* + * Make a database connection with the given parameters. An + * interactive password prompt is automatically issued if required. + * + * If fail_on_error is false, we return NULL without printing any message + * on failure, but preserve any prompted password for the next try. + * + * On success, the global variable 'connstr' is set to a connection string + * containing the options used. + */ +static PGconn * +connectDatabase(const char *dbname, const char *connection_string, + const char *pghost, const char *pgport, const char *pguser, + trivalue prompt_password, bool fail_on_error) +{ + PGconn *conn; + bool new_pass; + const char *remoteversion_str; + int my_version; + const char **keywords = NULL; + const char **values = NULL; + PQconninfoOption *conn_opts = NULL; + static char *password = NULL; + + if (prompt_password == TRI_YES && !password) + password = simple_prompt("Password: ", false); + + /* + * Start the connection. Loop until we have a password if requested by + * backend. + */ + do + { + int argcount = 6; + PQconninfoOption *conn_opt; + char *err_msg = NULL; + int i = 0; + + if (keywords) + free(keywords); + if (values) + free(values); + if (conn_opts) + PQconninfoFree(conn_opts); + + /* + * Merge the connection info inputs given in form of connection string + * and other options. Explicitly discard any dbname value in the + * connection string; otherwise, PQconnectdbParams() would interpret + * that value as being itself a connection string. + */ + if (connection_string) + { + conn_opts = PQconninfoParse(connection_string, &err_msg); + if (conn_opts == NULL) + { + pg_log_error("%s", err_msg); + exit_nicely(1); + } + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && + strcmp(conn_opt->keyword, "dbname") != 0) + argcount++; + } + + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && + strcmp(conn_opt->keyword, "dbname") != 0) + { + keywords[i] = conn_opt->keyword; + values[i] = conn_opt->val; + i++; + } + } + } + else + { + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + } + + if (pghost) + { + keywords[i] = "host"; + values[i] = pghost; + i++; + } + if (pgport) + { + keywords[i] = "port"; + values[i] = pgport; + i++; + } + if (pguser) + { + keywords[i] = "user"; + values[i] = pguser; + i++; + } + if (password) + { + keywords[i] = "password"; + values[i] = password; + i++; + } + if (dbname) + { + keywords[i] = "dbname"; + values[i] = dbname; + i++; + } + keywords[i] = "fallback_application_name"; + values[i] = progname; + i++; + + new_pass = false; + conn = PQconnectdbParams(keywords, values, true); + + if (!conn) + { + pg_log_error("could not connect to database \"%s\"", dbname); + exit_nicely(1); + } + + if (PQstatus(conn) == CONNECTION_BAD && + PQconnectionNeedsPassword(conn) && + !password && + prompt_password != TRI_NO) + { + PQfinish(conn); + password = simple_prompt("Password: ", false); + new_pass = true; + } + } while (new_pass); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) + { + if (fail_on_error) + { + pg_log_error("%s", PQerrorMessage(conn)); + exit_nicely(1); + } + else + { + PQfinish(conn); + + free(keywords); + free(values); + PQconninfoFree(conn_opts); + + return NULL; + } + } + + /* + * Ok, connected successfully. Remember the options used, in the form of a + * connection string. + */ + connstr = constructConnStr(keywords, values); + + free(keywords); + free(values); + PQconninfoFree(conn_opts); + + /* Check version */ + remoteversion_str = PQparameterStatus(conn, "server_version"); + if (!remoteversion_str) + { + pg_log_error("could not get server version"); + exit_nicely(1); + } + server_version = PQserverVersion(conn); + if (server_version == 0) + { + pg_log_error("could not parse server version \"%s\"", + remoteversion_str); + exit_nicely(1); + } + + my_version = PG_VERSION_NUM; + + /* + * We allow the server to be back to 8.0, and up to any minor release of + * our own major version. (See also version check in pg_dump.c.) + */ + if (my_version != server_version + && (server_version < 80000 || + (server_version / 100) > (my_version / 100))) + { + pg_log_error("server version: %s; %s version: %s", + remoteversion_str, progname, PG_VERSION); + pg_log_error("aborting because of server version mismatch"); + exit_nicely(1); + } + + PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL)); + + return conn; +} + +/* ---------- + * Construct a connection string from the given keyword/value pairs. It is + * used to pass the connection options to the pg_dump subprocess. + * + * The following parameters are excluded: + * dbname - varies in each pg_dump invocation + * password - it's not secure to pass a password on the command line + * fallback_application_name - we'll let pg_dump set it + * ---------- + */ +static char * +constructConnStr(const char **keywords, const char **values) +{ + PQExpBuffer buf = createPQExpBuffer(); + char *connstr; + int i; + bool firstkeyword = true; + + /* Construct a new connection string in key='value' format. */ + for (i = 0; keywords[i] != NULL; i++) + { + if (strcmp(keywords[i], "dbname") == 0 || + strcmp(keywords[i], "password") == 0 || + strcmp(keywords[i], "fallback_application_name") == 0) + continue; + + if (!firstkeyword) + appendPQExpBufferChar(buf, ' '); + firstkeyword = false; + appendPQExpBuffer(buf, "%s=", keywords[i]); + appendConnStrVal(buf, values[i]); + } + + connstr = pg_strdup(buf->data); + destroyPQExpBuffer(buf); + return connstr; +} + +/* + * Run a query, return the results, exit program on failure. + */ +static PGresult * +executeQuery(PGconn *conn, const char *query) +{ + PGresult *res; + + pg_log_info("executing %s", query); + + res = PQexec(conn, query); + if (!res || + PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("query failed: %s", PQerrorMessage(conn)); + pg_log_error("query was: %s", query); + PQfinish(conn); + exit_nicely(1); + } + + return res; +} + +/* + * As above for a SQL command (which returns nothing). + */ +static void +executeCommand(PGconn *conn, const char *query) +{ + PGresult *res; + + pg_log_info("executing %s", query); + + res = PQexec(conn, query); + if (!res || + PQresultStatus(res) != PGRES_COMMAND_OK) + { + pg_log_error("query failed: %s", PQerrorMessage(conn)); + pg_log_error("query was: %s", query); + PQfinish(conn); + exit_nicely(1); + } + + PQclear(res); +} + + +/* + * dumpTimestamp + */ +static void +dumpTimestamp(const char *msg) +{ + char buf[64]; + time_t now = time(NULL); + + if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&now)) != 0) + fprintf(OPF, "-- %s %s\n\n", msg, buf); +} diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c new file mode 100644 index 0000000..589b4ae --- /dev/null +++ b/src/bin/pg_dump/pg_restore.c @@ -0,0 +1,524 @@ +/*------------------------------------------------------------------------- + * + * pg_restore.c + * pg_restore is an utility extracting postgres database definitions + * from a backup archive created by pg_dump using the archiver + * interface. + * + * pg_restore will read the backup archive and + * dump out a script that reproduces + * the schema of the database in terms of + * user-defined types + * user-defined functions + * tables + * indexes + * aggregates + * operators + * ACL - grant/revoke + * + * the output script is SQL that is understood by PostgreSQL + * + * Basic process in a restore operation is: + * + * Open the Archive and read the TOC. + * Set flags in TOC entries, and *maybe* reorder them. + * Generate script to stdout + * Exit + * + * Copyright (c) 2000, Philip Warner + * Rights are granted to use this software in any way so long + * as this notice is not removed. + * + * The author is not responsible for loss or damages that may + * result from its use. + * + * + * IDENTIFICATION + * src/bin/pg_dump/pg_restore.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#include "dumputils.h" +#include "getopt_long.h" +#include "parallel.h" +#include "pg_backup_utils.h" + +static void usage(const char *progname); + +int +main(int argc, char **argv) +{ + RestoreOptions *opts; + int c; + int exit_code; + int numWorkers = 1; + Archive *AH; + char *inputFileSpec; + static int disable_triggers = 0; + static int enable_row_security = 0; + static int if_exists = 0; + static int no_data_for_failed_tables = 0; + static int outputNoTablespaces = 0; + static int use_setsessauth = 0; + static int no_comments = 0; + static int no_publications = 0; + static int no_security_labels = 0; + static int no_subscriptions = 0; + static int strict_names = 0; + + struct option cmdopts[] = { + {"clean", 0, NULL, 'c'}, + {"create", 0, NULL, 'C'}, + {"data-only", 0, NULL, 'a'}, + {"dbname", 1, NULL, 'd'}, + {"exit-on-error", 0, NULL, 'e'}, + {"exclude-schema", 1, NULL, 'N'}, + {"file", 1, NULL, 'f'}, + {"format", 1, NULL, 'F'}, + {"function", 1, NULL, 'P'}, + {"host", 1, NULL, 'h'}, + {"index", 1, NULL, 'I'}, + {"jobs", 1, NULL, 'j'}, + {"list", 0, NULL, 'l'}, + {"no-privileges", 0, NULL, 'x'}, + {"no-acl", 0, NULL, 'x'}, + {"no-owner", 0, NULL, 'O'}, + {"no-reconnect", 0, NULL, 'R'}, + {"port", 1, NULL, 'p'}, + {"no-password", 0, NULL, 'w'}, + {"password", 0, NULL, 'W'}, + {"schema", 1, NULL, 'n'}, + {"schema-only", 0, NULL, 's'}, + {"superuser", 1, NULL, 'S'}, + {"table", 1, NULL, 't'}, + {"trigger", 1, NULL, 'T'}, + {"use-list", 1, NULL, 'L'}, + {"username", 1, NULL, 'U'}, + {"verbose", 0, NULL, 'v'}, + {"single-transaction", 0, NULL, '1'}, + + /* + * the following options don't have an equivalent short option letter + */ + {"disable-triggers", no_argument, &disable_triggers, 1}, + {"enable-row-security", no_argument, &enable_row_security, 1}, + {"if-exists", no_argument, &if_exists, 1}, + {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1}, + {"no-tablespaces", no_argument, &outputNoTablespaces, 1}, + {"role", required_argument, NULL, 2}, + {"section", required_argument, NULL, 3}, + {"strict-names", no_argument, &strict_names, 1}, + {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + {"no-comments", no_argument, &no_comments, 1}, + {"no-publications", no_argument, &no_publications, 1}, + {"no-security-labels", no_argument, &no_security_labels, 1}, + {"no-subscriptions", no_argument, &no_subscriptions, 1}, + + {NULL, 0, NULL, 0} + }; + + pg_logging_init(argv[0]); + pg_logging_set_level(PG_LOG_WARNING); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump")); + + init_parallel_dump_utils(); + + opts = NewRestoreOptions(); + + progname = get_progname(argv[0]); + + if (argc > 1) + { + if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) + { + usage(progname); + exit_nicely(0); + } + if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) + { + puts("pg_restore (PostgreSQL) " PG_VERSION); + exit_nicely(0); + } + } + + while ((c = getopt_long(argc, argv, "acCd:ef:F:h:I:j:lL:n:N:Op:P:RsS:t:T:U:vwWx1", + cmdopts, NULL)) != -1) + { + switch (c) + { + case 'a': /* Dump data only */ + opts->dataOnly = 1; + break; + case 'c': /* clean (i.e., drop) schema prior to create */ + opts->dropSchema = 1; + break; + case 'C': + opts->createDB = 1; + break; + case 'd': + opts->cparams.dbname = pg_strdup(optarg); + break; + case 'e': + opts->exit_on_error = true; + break; + case 'f': /* output file name */ + opts->filename = pg_strdup(optarg); + break; + case 'F': + if (strlen(optarg) != 0) + opts->formatName = pg_strdup(optarg); + break; + case 'h': + if (strlen(optarg) != 0) + opts->cparams.pghost = pg_strdup(optarg); + break; + + case 'j': /* number of restore jobs */ + numWorkers = atoi(optarg); + break; + + case 'l': /* Dump the TOC summary */ + opts->tocSummary = 1; + break; + + case 'L': /* input TOC summary file name */ + opts->tocFile = pg_strdup(optarg); + break; + + case 'n': /* Dump data for this schema only */ + simple_string_list_append(&opts->schemaNames, optarg); + break; + + case 'N': /* Do not dump data for this schema */ + simple_string_list_append(&opts->schemaExcludeNames, optarg); + break; + + case 'O': + opts->noOwner = 1; + break; + + case 'p': + if (strlen(optarg) != 0) + opts->cparams.pgport = pg_strdup(optarg); + break; + case 'R': + /* no-op, still accepted for backwards compatibility */ + break; + case 'P': /* Function */ + opts->selTypes = 1; + opts->selFunction = 1; + simple_string_list_append(&opts->functionNames, optarg); + break; + case 'I': /* Index */ + opts->selTypes = 1; + opts->selIndex = 1; + simple_string_list_append(&opts->indexNames, optarg); + break; + case 'T': /* Trigger */ + opts->selTypes = 1; + opts->selTrigger = 1; + simple_string_list_append(&opts->triggerNames, optarg); + break; + case 's': /* dump schema only */ + opts->schemaOnly = 1; + break; + case 'S': /* Superuser username */ + if (strlen(optarg) != 0) + opts->superuser = pg_strdup(optarg); + break; + case 't': /* Dump specified table(s) only */ + opts->selTypes = 1; + opts->selTable = 1; + simple_string_list_append(&opts->tableNames, optarg); + break; + + case 'U': + opts->cparams.username = pg_strdup(optarg); + break; + + case 'v': /* verbose */ + opts->verbose = 1; + pg_logging_increase_verbosity(); + break; + + case 'w': + opts->cparams.promptPassword = TRI_NO; + break; + + case 'W': + opts->cparams.promptPassword = TRI_YES; + break; + + case 'x': /* skip ACL dump */ + opts->aclsSkip = 1; + break; + + case '1': /* Restore data in a single transaction */ + opts->single_txn = true; + opts->exit_on_error = true; + break; + + case 0: + + /* + * This covers the long options without a short equivalent. + */ + break; + + case 2: /* SET ROLE */ + opts->use_role = pg_strdup(optarg); + break; + + case 3: /* section */ + set_dump_section(optarg, &(opts->dumpSections)); + break; + + default: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit_nicely(1); + } + } + + /* Get file name from command line */ + if (optind < argc) + inputFileSpec = argv[optind++]; + else + inputFileSpec = NULL; + + /* Complain if any arguments remain */ + if (optind < argc) + { + pg_log_error("too many command-line arguments (first is \"%s\")", + argv[optind]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + + /* Complain if neither -f nor -d was specified (except if dumping TOC) */ + if (!opts->cparams.dbname && !opts->filename && !opts->tocSummary) + { + pg_log_error("one of -d/--dbname and -f/--file must be specified"); + exit_nicely(1); + } + + /* Should get at most one of -d and -f, else user is confused */ + if (opts->cparams.dbname) + { + if (opts->filename) + { + pg_log_error("options -d/--dbname and -f/--file cannot be used together"); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } + opts->useDB = 1; + } + + if (opts->dataOnly && opts->schemaOnly) + { + pg_log_error("options -s/--schema-only and -a/--data-only cannot be used together"); + exit_nicely(1); + } + + if (opts->dataOnly && opts->dropSchema) + { + pg_log_error("options -c/--clean and -a/--data-only cannot be used together"); + exit_nicely(1); + } + + /* + * -C is not compatible with -1, because we can't create a database inside + * a transaction block. + */ + if (opts->createDB && opts->single_txn) + { + pg_log_error("options -C/--create and -1/--single-transaction cannot be used together"); + exit_nicely(1); + } + + if (numWorkers <= 0) + { + pg_log_error("invalid number of parallel jobs"); + exit(1); + } + + /* See comments in pg_dump.c */ +#ifdef WIN32 + if (numWorkers > MAXIMUM_WAIT_OBJECTS) + { + pg_log_error("maximum number of parallel jobs is %d", + MAXIMUM_WAIT_OBJECTS); + exit(1); + } +#endif + + /* Can't do single-txn mode with multiple connections */ + if (opts->single_txn && numWorkers > 1) + { + pg_log_error("cannot specify both --single-transaction and multiple jobs"); + exit_nicely(1); + } + + opts->disable_triggers = disable_triggers; + opts->enable_row_security = enable_row_security; + opts->noDataForFailedTables = no_data_for_failed_tables; + opts->noTablespace = outputNoTablespaces; + opts->use_setsessauth = use_setsessauth; + opts->no_comments = no_comments; + opts->no_publications = no_publications; + opts->no_security_labels = no_security_labels; + opts->no_subscriptions = no_subscriptions; + + if (if_exists && !opts->dropSchema) + { + pg_log_error("option --if-exists requires option -c/--clean"); + exit_nicely(1); + } + opts->if_exists = if_exists; + opts->strict_names = strict_names; + + if (opts->formatName) + { + switch (opts->formatName[0]) + { + case 'c': + case 'C': + opts->format = archCustom; + break; + + case 'd': + case 'D': + opts->format = archDirectory; + break; + + case 't': + case 'T': + opts->format = archTar; + break; + + default: + pg_log_error("unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"", + opts->formatName); + exit_nicely(1); + } + } + + AH = OpenArchive(inputFileSpec, opts->format); + + SetArchiveOptions(AH, NULL, opts); + + /* + * We don't have a connection yet but that doesn't matter. The connection + * is initialized to NULL and if we terminate through exit_nicely() while + * it's still NULL, the cleanup function will just be a no-op. + */ + on_exit_close_archive(AH); + + /* Let the archiver know how noisy to be */ + AH->verbose = opts->verbose; + + /* + * Whether to keep submitting sql commands as "pg_restore ... | psql ... " + */ + AH->exit_on_error = opts->exit_on_error; + + if (opts->tocFile) + SortTocFromFile(AH); + + AH->numWorkers = numWorkers; + + if (opts->tocSummary) + PrintTOCSummary(AH); + else + { + ProcessArchiveRestoreOptions(AH); + RestoreArchive(AH); + } + + /* done, print a summary of ignored errors */ + if (AH->n_errors) + pg_log_warning("errors ignored on restore: %d", AH->n_errors); + + /* AH may be freed in CloseArchive? */ + exit_code = AH->n_errors ? 1 : 0; + + CloseArchive(AH); + + return exit_code; +} + +static void +usage(const char *progname) +{ + printf(_("%s restores a PostgreSQL database from an archive created by pg_dump.\n\n"), progname); + printf(_("Usage:\n")); + printf(_(" %s [OPTION]... [FILE]\n"), progname); + + printf(_("\nGeneral options:\n")); + printf(_(" -d, --dbname=NAME connect to database name\n")); + printf(_(" -f, --file=FILENAME output file name (- for stdout)\n")); + printf(_(" -F, --format=c|d|t backup file format (should be automatic)\n")); + printf(_(" -l, --list print summarized TOC of the archive\n")); + printf(_(" -v, --verbose verbose mode\n")); + printf(_(" -V, --version output version information, then exit\n")); + printf(_(" -?, --help show this help, then exit\n")); + + printf(_("\nOptions controlling the restore:\n")); + printf(_(" -a, --data-only restore only the data, no schema\n")); + printf(_(" -c, --clean clean (drop) database objects before recreating\n")); + printf(_(" -C, --create create the target database\n")); + printf(_(" -e, --exit-on-error exit on error, default is to continue\n")); + printf(_(" -I, --index=NAME restore named index\n")); + printf(_(" -j, --jobs=NUM use this many parallel jobs to restore\n")); + printf(_(" -L, --use-list=FILENAME use table of contents from this file for\n" + " selecting/ordering output\n")); + printf(_(" -n, --schema=NAME restore only objects in this schema\n")); + printf(_(" -N, --exclude-schema=NAME do not restore objects in this schema\n")); + printf(_(" -O, --no-owner skip restoration of object ownership\n")); + printf(_(" -P, --function=NAME(args) restore named function\n")); + printf(_(" -s, --schema-only restore only the schema, no data\n")); + printf(_(" -S, --superuser=NAME superuser user name to use for disabling triggers\n")); + printf(_(" -t, --table=NAME restore named relation (table, view, etc.)\n")); + printf(_(" -T, --trigger=NAME restore named trigger\n")); + printf(_(" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n")); + printf(_(" -1, --single-transaction restore as a single transaction\n")); + printf(_(" --disable-triggers disable triggers during data-only restore\n")); + printf(_(" --enable-row-security enable row security\n")); + printf(_(" --if-exists use IF EXISTS when dropping objects\n")); + printf(_(" --no-comments do not restore comments\n")); + printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n" + " created\n")); + printf(_(" --no-publications do not restore publications\n")); + printf(_(" --no-security-labels do not restore security labels\n")); + printf(_(" --no-subscriptions do not restore subscriptions\n")); + printf(_(" --no-tablespaces do not restore tablespace assignments\n")); + printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n")); + printf(_(" --strict-names require table and/or schema include patterns to\n" + " match at least one entity each\n")); + printf(_(" --use-set-session-authorization\n" + " use SET SESSION AUTHORIZATION commands instead of\n" + " ALTER OWNER commands to set ownership\n")); + + printf(_("\nConnection options:\n")); + printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); + printf(_(" -p, --port=PORT database server port number\n")); + printf(_(" -U, --username=NAME connect as specified database user\n")); + printf(_(" -w, --no-password never prompt for password\n")); + printf(_(" -W, --password force password prompt (should happen automatically)\n")); + printf(_(" --role=ROLENAME do SET ROLE before restore\n")); + + printf(_("\n" + "The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" + "multiple times to select multiple objects.\n")); + printf(_("\nIf no input file name is supplied, then standard input is used.\n\n")); + printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); + printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); +} diff --git a/src/bin/pg_dump/po/cs.po b/src/bin/pg_dump/po/cs.po new file mode 100644 index 0000000..3319e53 --- /dev/null +++ b/src/bin/pg_dump/po/cs.po @@ -0,0 +1,2965 @@ +# Czech message translation file for pg_dump +# Copyright (C) 2012 PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# +# Tomas Vondra , 2012, 2013. +msgid "" +msgstr "" +"Project-Id-Version: pg_dump-cs (PostgreSQL 9.3)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2020-10-31 16:16+0000\n" +"PO-Revision-Date: 2021-09-16 09:14+0200\n" +"Last-Translator: Tomas Vondra \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Poedit 2.4.1\n" + +#: ../../../src/common/logging.c:236 +#, c-format +msgid "fatal: " +msgstr "fatal: " + +#: ../../../src/common/logging.c:243 +#, c-format +msgid "error: " +msgstr "chyba " + +#: ../../../src/common/logging.c:250 +#, c-format +msgid "warning: " +msgstr "varování: " + +#: ../../common/exec.c:137 ../../common/exec.c:254 ../../common/exec.c:300 +#, c-format +msgid "could not identify current directory: %m" +msgstr "nelze získat aktuální adresář: %m" + +#: ../../common/exec.c:156 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "neplatný binární soubor\"%s\"" + +#: ../../common/exec.c:206 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "nelze číst binární soubor \"%s\"" + +#: ../../common/exec.c:214 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "nelze najít soubor \"%s\" ke spuštění" + +#: ../../common/exec.c:270 ../../common/exec.c:309 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "nelze změnit adresář na \"%s\" : %m" + +#: ../../common/exec.c:287 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "nelze přečíst symbolický odkaz \"%s\": %m" + +#: ../../common/exec.c:410 +#, c-format +msgid "pclose failed: %m" +msgstr "volání pclose selhalo: %m" + +#: ../../common/exec.c:539 ../../common/exec.c:584 ../../common/exec.c:676 +msgid "out of memory" +msgstr "nedostatek paměti" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "nedostatek paměti\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nelze duplikovat null pointer (interní chyba)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "příkaz není spustitelný" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "příkaz nenalezen" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "potomek skončil s návratovým kódem %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "potomek byl ukončen vyjímkou 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "potomek byl ukončen signálem %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "potomek skončil s nerozponaným stavem %d" + +#: common.c:121 +#, c-format +msgid "reading extensions" +msgstr "čtu rozšíření" + +#: common.c:125 +#, c-format +msgid "identifying extension members" +msgstr "hledám položky rozšíření (extenze)" + +#: common.c:128 +#, c-format +msgid "reading schemas" +msgstr "čtu schémata" + +#: common.c:138 +#, c-format +msgid "reading user-defined tables" +msgstr "čtu uživatelem definované tabulky" + +#: common.c:145 +#, c-format +msgid "reading user-defined functions" +msgstr "čtu uživatelem definované funkce" + +#: common.c:150 +#, c-format +msgid "reading user-defined types" +msgstr "čtu uživatelem definované typy" + +#: common.c:155 +#, c-format +msgid "reading procedural languages" +msgstr "čtu procedurální jazyky" + +#: common.c:158 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "čtu uživatelem definované agregátní funkce" + +#: common.c:161 +#, c-format +msgid "reading user-defined operators" +msgstr "čtu uživatelem definované operátory" + +#: common.c:165 +#, c-format +msgid "reading user-defined access methods" +msgstr "čtu uživatelem definované přístupové metody" + +#: common.c:168 +#, c-format +msgid "reading user-defined operator classes" +msgstr "čtu uživatelem definované třídy operátorů" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator families" +msgstr "čtu uživatelem definované rodiny operátorů" + +#: common.c:174 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "čtu uživatelem definované fulltextové parsery" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search templates" +msgstr "čtu uživatelem definované fulltextové šablony" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "čtu uživatelem definované fulltextové slovníky" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "čtu uživatelské fulltextového konfigurace" + +#: common.c:186 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "čtu uživatelem definované foreign-data wrappery" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "čtu uživatelem definované foreign servery" + +#: common.c:192 +#, c-format +msgid "reading default privileges" +msgstr "čtu implicitní přístupová práva" + +#: common.c:195 +#, c-format +msgid "reading user-defined collations" +msgstr "čtu uživatelem definované collations" + +#: common.c:199 +#, c-format +msgid "reading user-defined conversions" +msgstr "čtu uživatelem definované konverze" + +#: common.c:202 +#, c-format +msgid "reading type casts" +msgstr "čtu přetypování" + +#: common.c:205 +#, c-format +msgid "reading transforms" +msgstr "čtu transformace" + +#: common.c:208 +#, c-format +msgid "reading table inheritance information" +msgstr "čtu informace dědičnosti tabulky" + +#: common.c:211 +#, c-format +msgid "reading event triggers" +msgstr "čtu event triggery" + +#: common.c:215 +#, c-format +msgid "finding extension tables" +msgstr "hledám tabulky pro rozšíření" + +#: common.c:219 +#, c-format +msgid "finding inheritance relationships" +msgstr "hledám informace o dědičnosti" + +#: common.c:222 +#, c-format +msgid "reading column info for interesting tables" +msgstr "čtu informace o sloupcích pro tabulky" + +#: common.c:225 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "označuji zděděné sloupce v pod-tabulkách" + +#: common.c:228 +#, c-format +msgid "reading indexes" +msgstr "čtu indexy" + +#: common.c:231 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "označuji indexy na partitionovaných tabulkách" + +#: common.c:234 +#, c-format +msgid "reading extended statistics" +msgstr "čtu rozšířené statistiky" + +#: common.c:237 +#, c-format +msgid "reading constraints" +msgstr "čtu omezení" + +#: common.c:240 +#, c-format +msgid "reading triggers" +msgstr "čtu triggery" + +#: common.c:243 +#, c-format +msgid "reading rewrite rules" +msgstr "čtu přepisovací pravidla" + +#: common.c:246 +#, c-format +msgid "reading policies" +msgstr "čtu přístupové politiky" + +#: common.c:249 +#, c-format +msgid "reading publications" +msgstr "čtu publikace" + +#: common.c:252 +#, c-format +msgid "reading publication membership" +msgstr "čtu členství v publikacích" + +#: common.c:255 +#, c-format +msgid "reading subscriptions" +msgstr "čtu subskripce" + +#: common.c:1025 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "selhala kontrola, rodičovské OID %u tabulky \"%s\" (OID %u) nenalez" + +#: common.c:1067 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "nemohu zpracovat numerické pole \"%s\": příliš mnoho čísel" + +#: common.c:1082 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "nemohu zpracovat numerické pole \"%s\": neplatný znak v čísle" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "neplatný kompresní kód: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "nezkompilováno s podporou zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "nelze inicializovat kompresní knihovnu: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "nelze uzavřít kompresní stream: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "nelze komprimovat data: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "nelze dekomprimovat data: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "nelze uzavřít kompresní knihovnu: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:557 pg_backup_tar.c:560 +#, c-format +msgid "could not read from input file: %s" +msgstr "nelze číst vstupní soubor: %s" + +#: compress_io.c:623 pg_backup_custom.c:646 pg_backup_directory.c:552 +#: pg_backup_tar.c:793 pg_backup_tar.c:816 +#, c-format +msgid "could not read from input file: end of file" +msgstr "nelze číst vstupní soubor: end of file" + +#: parallel.c:254 +#, c-format +msgid "WSAStartup failed: %d" +msgstr "WSAStartup selhal: %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "nelze vytvořit komunikační kanály: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "nelze vytvořit pracovní proces: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from master: \"%s\"" +msgstr "nerozpoznaný příkaz obdržen od mastera: %s" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "z pracovního procesu dorazila neplatná zpráva: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"nelze získat zámek na relaci \"%s\"\n" +"Toto obvykle znamená že někdo si vyžádal ACCESS EXCLUSIVE zámek na tabulce poté co rodičovský pg_dump proces získal výchozí ACCESS SHARE zámek na dané tabulce." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "pracovní proces neočekávaně selhal" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "nelze zapsat do komunikačního kanálu: %m" + +#: parallel.c:1614 +#, c-format +msgid "select() failed: %m" +msgstr "select() selhalo: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: nelze vytvořit soket: chybový kód %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: nelze provést bind: chybový kód %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: nelze poslouchat: chybový kód %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: getsockname() failed: error code %d" +msgstr "pgpipe: getsockname() selhal: chybový kód %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: nelze vytvořit druhý soket: chybový kód %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: nelze se připojit k soketu: chybový kód %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: nelze přijmout spojení: chybový kód %d" + +#: pg_backup_archiver.c:277 pg_backup_archiver.c:1587 +#, c-format +msgid "could not close output file: %m" +msgstr "nelze zavřít výstupní soubor: %m" + +#: pg_backup_archiver.c:321 pg_backup_archiver.c:325 +#, c-format +msgid "archive items not in correct section order" +msgstr "archivované položky v nesprávném pořadí sekcí" + +#: pg_backup_archiver.c:331 +#, c-format +msgid "unexpected section code %d" +msgstr "neočekávaný kód sekce %d" + +#: pg_backup_archiver.c:368 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "paralelní obnova není pro tento formát archivu podporována" + +#: pg_backup_archiver.c:372 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "paralelní obnova není podporována s archivy z pre-8.0 verzí pg_dump" + +#: pg_backup_archiver.c:390 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "nelze obnovit z komprimovaného archivu (není nastavena podpora komprese)" + +#: pg_backup_archiver.c:407 +#, c-format +msgid "connecting to database for restore" +msgstr "navazováno spojení s databází pro obnovu" + +#: pg_backup_archiver.c:409 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "přímé spojení s databází nejsou podporovány v archivech před verzí 1.3" + +#: pg_backup_archiver.c:452 +#, c-format +msgid "implied data-only restore" +msgstr "předpokládána pouze obnova dat" + +#: pg_backup_archiver.c:518 +#, c-format +msgid "dropping %s %s" +msgstr "odstraňuji %s %s" + +#: pg_backup_archiver.c:613 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "nelze zjistit kam přidat IF EXISTS v příkazu \"%s\"" + +#: pg_backup_archiver.c:769 pg_backup_archiver.c:771 +#, c-format +msgid "warning from original dump file: %s" +msgstr "varování z originálního dump souboru: %s" + +#: pg_backup_archiver.c:786 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "vytvářím %s \"%s.%s\"" + +#: pg_backup_archiver.c:789 +#, c-format +msgid "creating %s \"%s\"" +msgstr "vytvářím %s \"%s\"" + +#: pg_backup_archiver.c:839 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "připojuji se k nové databázi \"%s\"" + +#: pg_backup_archiver.c:866 +#, c-format +msgid "processing %s" +msgstr "zpracovávám %s" + +#: pg_backup_archiver.c:886 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "zpracovávám data pro tabulku \"%s.%s\"" + +#: pg_backup_archiver.c:948 +#, c-format +msgid "executing %s %s" +msgstr "vykonávám %s %s" + +#: pg_backup_archiver.c:987 +#, c-format +msgid "disabling triggers for %s" +msgstr "vypínám triggery pro %s" + +#: pg_backup_archiver.c:1013 +#, c-format +msgid "enabling triggers for %s" +msgstr "zapínám triggery pro %s" + +#: pg_backup_archiver.c:1041 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "interní chyba -- WriteData není možno volat mimo kontext rutiny DataDumper" + +#: pg_backup_archiver.c:1224 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "\"large object\" výstup není podporován ve vybraném formátu" + +#: pg_backup_archiver.c:1282 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "obnoven %d large objekt" +msgstr[1] "obnoveny %d large objekty" +msgstr[2] "obnoveny %d large objektů" + +#: pg_backup_archiver.c:1303 pg_backup_tar.c:736 +#, c-format +msgid "restoring large object with OID %u" +msgstr "obnovován \"large object\" s OID %u" + +#: pg_backup_archiver.c:1315 +#, c-format +msgid "could not create large object %u: %s" +msgstr "nelze vytvořit \"large object\" %u: %s" + +#: pg_backup_archiver.c:1320 pg_dump.c:3555 +#, c-format +msgid "could not open large object %u: %s" +msgstr "nelze otevřít \"large object\" %u:%s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "nelze otevřít TOC soubor \"%s\": %m" + +#: pg_backup_archiver.c:1417 +#, c-format +msgid "line ignored: %s" +msgstr "řádka ignorována: %s" + +#: pg_backup_archiver.c:1424 +#, c-format +msgid "could not find entry for ID %d" +msgstr "nelze najít záznam ID %d" + +#: pg_backup_archiver.c:1445 pg_backup_directory.c:222 +#: pg_backup_directory.c:598 +#, c-format +msgid "could not close TOC file: %m" +msgstr "nelze zavřít TOC soubor: %m" + +#: pg_backup_archiver.c:1559 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:585 pg_backup_directory.c:648 +#: pg_backup_directory.c:667 pg_dumpall.c:484 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "nelze otevřít výstupní soubor \"%s\": %m" + +#: pg_backup_archiver.c:1561 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "nelze otevřít výstupní soubor: %m" + +#: pg_backup_archiver.c:1654 +#, c-format +msgid "wrote %lu byte of large object data (result = %lu)" +msgid_plural "wrote %lu bytes of large object data (result = %lu)" +msgstr[0] "zapsán %lu byte dat large objektů (result = %lu)" +msgstr[1] "zapsán %lu byty dat large objektů (result = %lu)" +msgstr[2] "zapsán %lu bytů dat large objektů (result = %lu)" + +#: pg_backup_archiver.c:1659 +#, c-format +msgid "could not write to large object (result: %lu, expected: %lu)" +msgstr "nelze zapsat \"large object\" (výsledek = %lu, očekáváno: %lu)" + +#: pg_backup_archiver.c:1749 +#, c-format +msgid "while INITIALIZING:" +msgstr "během INICIALIZACE:" + +#: pg_backup_archiver.c:1754 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "během ZPRACOVÁNÍ TOC:" + +#: pg_backup_archiver.c:1759 +#, c-format +msgid "while FINALIZING:" +msgstr "během FINALIZACE:" + +#: pg_backup_archiver.c:1764 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "z TOC záznamu %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1840 +#, c-format +msgid "bad dumpId" +msgstr "neplatné dumpId" + +#: pg_backup_archiver.c:1861 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "špatné dumpId tabulky pro TABLE DATA položku" + +#: pg_backup_archiver.c:1953 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "neočekávaný příznak datového offsetu %d" + +#: pg_backup_archiver.c:1966 +#, c-format +msgid "file offset in dump file is too large" +msgstr "offset souboru v dumpu je příliš velký" + +#: pg_backup_archiver.c:2103 pg_backup_archiver.c:2113 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "jméno adresáře je příliš dlouhé: \"%s\"" + +#: pg_backup_archiver.c:2121 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "adresář \"%s\" zřejmě není platným archivem (\"toc.dat\" neexistuje)" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:173 pg_backup_custom.c:812 +#: pg_backup_directory.c:207 pg_backup_directory.c:394 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "nelze otevřít vstupní soubor \"%s\": %m" + +#: pg_backup_archiver.c:2136 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "nelze otevřít vstupní soubor: %m" + +#: pg_backup_archiver.c:2142 +#, c-format +msgid "could not read input file: %m" +msgstr "nelze číst vstupní soubor: %m" + +#: pg_backup_archiver.c:2144 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "vstupní soubor je příliš krátký (čteno %lu, očekáváno 5)" + +#: pg_backup_archiver.c:2229 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "vstupní soubor se zdá být dump v textovém formátu. Použijte prosím psql." + +#: pg_backup_archiver.c:2235 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "vstupní soubor se nezdá být korektním archivem (příliš krátký?)" + +#: pg_backup_archiver.c:2241 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "vstupní soubor se nezdá být korektním archivem" + +#: pg_backup_archiver.c:2261 +#, c-format +msgid "could not close input file: %m" +msgstr "nelze zavřít výstupní soubor: %m" + +#: pg_backup_archiver.c:2373 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "neznámý formát souboru \"%d\"" + +#: pg_backup_archiver.c:2455 pg_backup_archiver.c:4458 +#, c-format +msgid "finished item %d %s %s" +msgstr "dokončena položka %d %s %s" + +#: pg_backup_archiver.c:2459 pg_backup_archiver.c:4471 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "worker proces selhal: exit kód %d" + +#: pg_backup_archiver.c:2579 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "ID záznamu %d je mimo rozsah -- možná je poškozena TOC" + +#: pg_backup_archiver.c:2646 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "obnova tabulek s volbou WITH OIDS již není podporována" + +#: pg_backup_archiver.c:2728 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "neplatné kódování \"%s\"" + +#: pg_backup_archiver.c:2733 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "chybná položka ENCODING: %s" + +#: pg_backup_archiver.c:2751 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "chybná položka STDSTRINGS: %s" + +#: pg_backup_archiver.c:2776 +#, c-format +msgid "schema \"%s\" not found" +msgstr "schéma \"%s\" nenalezeno" + +#: pg_backup_archiver.c:2783 +#, c-format +msgid "table \"%s\" not found" +msgstr "tabulka \"%s\" nenalezena" + +#: pg_backup_archiver.c:2790 +#, c-format +msgid "index \"%s\" not found" +msgstr "index \"%s\" nenalezen" + +#: pg_backup_archiver.c:2797 +#, c-format +msgid "function \"%s\" not found" +msgstr "funkce \"%s\" nenalezena" + +#: pg_backup_archiver.c:2804 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "trigger \"%s\" nenalezen" + +#: pg_backup_archiver.c:3196 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "nelze nastavit uživatele session na \"%s\": %s" + +#: pg_backup_archiver.c:3328 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "nelze nastavit search_path na \"%s\": %s" + +#: pg_backup_archiver.c:3390 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "nelze nastavit default_tablespace na %s: %s" + +#: pg_backup_archiver.c:3435 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "nelze nastavit default_table_access_method na: %s" + +#: pg_backup_archiver.c:3527 pg_backup_archiver.c:3685 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "nevím jak nastavit vlastníka pro typ objektu \"%s\"" + +#: pg_backup_archiver.c:3789 +#, c-format +msgid "did not find magic string in file header" +msgstr "nelze najít identifikační řetězec v hlavičce souboru" + +#: pg_backup_archiver.c:3802 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "nepodporovaná verze (%d.%d) v hlavičce souboru" + +#: pg_backup_archiver.c:3807 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "kontrola velikosti integeru (%lu) selhala" + +#: pg_backup_archiver.c:3811 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "archiv byl vytvořen na stroji s většími celými čísly (integer), některé operace mohou selhat" + +#: pg_backup_archiver.c:3821 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "očekávaný formát (%d) se liší se od formátu nalezeného v souboru (%d)" + +#: pg_backup_archiver.c:3837 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "archiv je komprimován, ale tato instalace nepodporuje kompresi -- data nebudou dostupná" + +#: pg_backup_archiver.c:3855 +#, c-format +msgid "invalid creation date in header" +msgstr "v hlavičce je neplatné datum vytvoření" + +#: pg_backup_archiver.c:3983 +#, c-format +msgid "processing item %d %s %s" +msgstr "zpracovávám položku %d %s %s" + +#: pg_backup_archiver.c:4062 +#, c-format +msgid "entering main parallel loop" +msgstr "vstupuji do hlavní paralelní smyčky" + +#: pg_backup_archiver.c:4073 +#, c-format +msgid "skipping item %d %s %s" +msgstr "přeskakuji položku %d %s %s" + +#: pg_backup_archiver.c:4082 +#, c-format +msgid "launching item %d %s %s" +msgstr "spouštím položku %d %s %s" + +#: pg_backup_archiver.c:4136 +#, c-format +msgid "finished main parallel loop" +msgstr "ukončuji hlavní paralelní smyčku" + +#: pg_backup_archiver.c:4172 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "zpracování vynechalo položku %d %s %s" + +#: pg_backup_archiver.c:4777 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "tabulku \"%s\" nelze vytvořit, její data nebudou obnovena" + +#: pg_backup_custom.c:378 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "neplatné OID pro \"large object\"" + +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:632 +#: pg_backup_custom.c:870 pg_backup_tar.c:1086 pg_backup_tar.c:1091 +#, c-format +msgid "error during file seek: %m" +msgstr "chyba během posunu v souboru: %m" + +#: pg_backup_custom.c:480 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "datový blok %d má chybnou seek pozici" + +#: pg_backup_custom.c:497 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "nepřípustný typ datového bloku (%d) během prohledávání archivu" + +#: pg_backup_custom.c:519 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "v archivu nelze najít blok ID %d -- možná kvůli out-of-order restore požadavku, který nemohl být vyřízen kvůli non-seekable vstupnímu souboru" + +#: pg_backup_custom.c:524 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "v archivu nelze najít blok ID %d -- archiv může být poškozen" + +#: pg_backup_custom.c:531 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "nalezeno neočekávané ID bloku (%d) při čtení dat - očekáváno %d" + +#: pg_backup_custom.c:545 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "nepřípustný typ datového bloku %d během obnovení archivu" + +#: pg_backup_custom.c:648 +#, c-format +msgid "could not read from input file: %m" +msgstr "nelze číst vstupní soubor: %m" + +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:948 +#: pg_backup_tar.c:1089 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "nelze určit seek pozici v archivním souboru: %m" + +#: pg_backup_custom.c:767 pg_backup_custom.c:807 +#, c-format +msgid "could not close archive file: %m" +msgstr "nelze uzavřít archivní soubor: %m" + +#: pg_backup_custom.c:790 +#, c-format +msgid "can only reopen input archives" +msgstr "vstupní archivy lze pouze znovu otevřít" + +#: pg_backup_custom.c:797 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "paralelní obnova ze standardního vstupnu není podporována" + +#: pg_backup_custom.c:799 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "paralelní obnova z neseekovatelného souboru není podporována" + +#: pg_backup_custom.c:815 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "nelze nastavit seek pozici v archivním souboru: %m" + +#: pg_backup_custom.c:894 +#, c-format +msgid "compressor active" +msgstr "compressor aktivní" + +#: pg_backup_db.c:41 +#, c-format +msgid "could not get server_version from libpq" +msgstr "nelze získat server_version z libpq" + +#: pg_backup_db.c:52 pg_dumpall.c:1826 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "verze serveru: %s; %s verze: %s" + +#: pg_backup_db.c:54 pg_dumpall.c:1828 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "končím kvůli rozdílnosti verzí serverů" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "spojení s databází již existuje" + +#: pg_backup_db.c:133 pg_backup_db.c:185 pg_dumpall.c:1651 pg_dumpall.c:1764 +msgid "Password: " +msgstr "Heslo: " + +#: pg_backup_db.c:177 +#, c-format +msgid "could not connect to database" +msgstr "nelze znovu navázat spojení s databází" + +#: pg_backup_db.c:195 +#, c-format +msgid "reconnection to database \"%s\" failed: %s" +msgstr "připojení k databázi \"%s\" selhalo: %s" + +#: pg_backup_db.c:199 +#, c-format +msgid "connection to database \"%s\" failed: %s" +msgstr "spojení s databází \"%s\" selhalo: %s" + +#: pg_backup_db.c:272 pg_dumpall.c:1684 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:279 pg_dumpall.c:1889 pg_dumpall.c:1912 +#, c-format +msgid "query failed: %s" +msgstr "dotaz selhal: %s" + +#: pg_backup_db.c:281 pg_dumpall.c:1890 pg_dumpall.c:1913 +#, c-format +msgid "query was: %s" +msgstr "dotaz byl: %s" + +#: pg_backup_db.c:322 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "dotaz vrátil %d řádku namísto jedné: %s" +msgstr[1] "dotaz vrátil %d řádky namísto jedné: %s" +msgstr[2] "dotaz vrátil %d řádek namísto jedné: %s" + +#: pg_backup_db.c:358 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sPříkaz byl: %s" + +#: pg_backup_db.c:414 pg_backup_db.c:488 pg_backup_db.c:495 +msgid "could not execute query" +msgstr "nelze provést dotaz" + +#: pg_backup_db.c:467 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "chyba vrácená voláním PQputCopyData: %s" + +#: pg_backup_db.c:516 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "chyba vrícená voláním PQputCopyEnd: %s" + +#: pg_backup_db.c:522 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY selhal pro tabulku \"%s\": %s" + +#: pg_backup_db.c:528 pg_dump.c:1991 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "neočekávané další výsledky během COPY tabulky \"%s\"" + +#: pg_backup_db.c:586 +#, c-format +msgid "LOCK TABLE failed for \"%s\": %s" +msgstr "LOCK TABLE selhal pro \"%s\": %s" + +#: pg_backup_db.c:604 +msgid "could not start database transaction" +msgstr "nelze spustit databázovou transakci" + +#: pg_backup_db.c:612 +msgid "could not commit database transaction" +msgstr "nelze provést commit transakce" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "nezadán žádný výstupní adresář" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "nelze načíst adresář \"%s\": %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "nelze zavřít adresář \"%s\": %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "nelze vytvořit adresář \"%s\": %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:496 +#: pg_backup_directory.c:532 +#, c-format +msgid "could not write to output file: %s" +msgstr "nelze zapsat do výstupního souboru: %s" + +#: pg_backup_directory.c:406 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "nelze uzavřít datový soubor \"%s\": %m" + +#: pg_backup_directory.c:446 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "nelze otevřít TOC soubor pro large objekty \"%s\" pro vstup: %m" + +#: pg_backup_directory.c:457 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "neplatný řádek v TOC souboru pro large objekty \"%s\" : \"%s\"" + +#: pg_backup_directory.c:466 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "chyba při čtení TOC souboru pro large objekty \"%s\"" + +#: pg_backup_directory.c:470 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "nelze uzavřít TOC soubor pro large objekty \"%s\": %m" + +#: pg_backup_directory.c:689 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "nelze zapsat do TOC souboru pro bloby" + +#: pg_backup_directory.c:721 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "jméno souboru je příliš dlouhé: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "tento formát nelze číst" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "nelze otevřít TOC soubor \"%s\" pro výstup: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "nelze otevřít TOC soubor pro výstup: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:358 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "komprese není podporována v archivním formátu tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "nelze otevřít TOC soubor \"%s\" pro vstup: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "nelze otevřít TOC soubor pro vstup: %m" + +#: pg_backup_tar.c:344 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "v archivu nelze najít soubor \"%s\"" + +#: pg_backup_tar.c:410 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "nelze vygenerovat jméno dočasného souboru: %m" + +#: pg_backup_tar.c:421 +#, c-format +msgid "could not open temporary file" +msgstr "nelze otevřít dočasný soubor" + +#: pg_backup_tar.c:448 +#, c-format +msgid "could not close tar member" +msgstr "nelze zavřít tar položku" + +#: pg_backup_tar.c:691 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "neočekávaná syntaxe příkazu COPY: \"%s\"" + +#: pg_backup_tar.c:958 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "neplatné OID pro \"large object\" (%u)" + +#: pg_backup_tar.c:1105 +#, c-format +msgid "could not close temporary file: %m" +msgstr "nelze otevřít dočasný soubor: %m" + +#: pg_backup_tar.c:1114 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "skutečná délka souboru (%s) neodpovídá očekávané (%s)" + +#: pg_backup_tar.c:1171 pg_backup_tar.c:1201 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "nelze najít hlavičku pro soubor %s v tar archivu" + +#: pg_backup_tar.c:1189 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "obnova dat mimo pořadí není podporována v tomto formátu archivu: \"%s\" je vyžadován, ale v archivu předchází \"%s\"." + +#: pg_backup_tar.c:1234 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "nalezena nekompletní tar hlavička (%lu byte)" +msgstr[1] "nalezena nekompletní tar hlavička (%lu byty)" +msgstr[2] "nalezena nekompletní tar hlavička (%lu bytů)" + +#: pg_backup_tar.c:1285 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "nalezena poškozená tar hlavička v %s (očekáváno %d, vypočteno %d) pozice souboru %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "neznámý název sekce \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:607 pg_dump.c:624 pg_dumpall.c:338 +#: pg_dumpall.c:348 pg_dumpall.c:357 pg_dumpall.c:366 pg_dumpall.c:374 +#: pg_dumpall.c:388 pg_dumpall.c:464 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Zkuste \"%s --help\" pro více informací.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "vyčerpány dostupné on_exit_nicely sloty" + +#: pg_dump.c:533 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "úroveň komprese musí být v rozsahu 0..9" + +#: pg_dump.c:571 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits musí být v intervalu -15..3" + +#: pg_dump.c:594 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "počet řádek na insert musí být v rozsahu %d..%d" + +#: pg_dump.c:622 pg_dumpall.c:346 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "příliš mnoho argumentů v příkazové řádce (první je \"%s\")" + +#: pg_dump.c:643 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "volby -s/--schema-only a -a/--data-only nelze používat společně" + +#: pg_dump.c:648 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "volby -s/--schema-only a --include-foreign-data nelze používat společně" + +#: pg_dump.c:651 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "volba --include-foreign-data není podporována pro paralelní backupy" + +#: pg_dump.c:655 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "volby -c/--clean a -a/--data-only nelze používat společně" + +#: pg_dump.c:660 pg_dumpall.c:381 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "volba --if-exists vyžaduje volbu -c/--clean" + +#: pg_dump.c:667 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "volba --on-conflict-do-nothing vyžaduje volbu --inserts, --rows-per-insert, nebo --column-inserts" + +#: pg_dump.c:689 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "požadovaná komprese není v této instalaci dostupná -- archiv bude nekomprimovaný" + +#: pg_dump.c:710 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "neplatný počet paralelních jobů" + +#: pg_dump.c:714 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "paralelní záloha je podporována pouze directory formátem" + +#: pg_dump.c:769 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synchronizované snapshoty nejsou na této verzi serveru podporovány.\n" +"Pokud nepotřebujete synchronizované snapshoty, použijte přepínač\n" +"--no-synchronized-snapshots." + +#: pg_dump.c:775 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Exportované snapshoty nejsou touto verzí serveru podporovány." + +#: pg_dump.c:787 +#, c-format +msgid "last built-in OID is %u" +msgstr "poslední vestavěné OID je %u" + +#: pg_dump.c:796 +#, c-format +msgid "no matching schemas were found" +msgstr "nebyla nalezena žádná odovídající schémata" + +#: pg_dump.c:810 +#, c-format +msgid "no matching tables were found" +msgstr "nebyla nalezena žádná odpovídající tabulka" + +#: pg_dump.c:990 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s vytvoří dump databáze jako textový soubor nebo v jiném formátu.\n" +"\n" + +#: pg_dump.c:991 pg_dumpall.c:617 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Použití:\n" + +#: pg_dump.c:992 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [PŘEPÍNAČ]... [DATABÁZE]\n" + +#: pg_dump.c:994 pg_dumpall.c:620 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Obecné volby:\n" + +#: pg_dump.c:995 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=SOUBOR výstupní soubor nebo adresář\n" + +#: pg_dump.c:996 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p formát výstupního soubor (custom, directory, tar,\n" +" plain text (výchozí))\n" + +#: pg_dump.c:998 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM použij tento počet paralelních jobů pro zálohu\n" + +#: pg_dump.c:999 pg_dumpall.c:622 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose vypisovat více informací\n" + +#: pg_dump.c:1000 pg_dumpall.c:623 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version zobraz informaci o verzi, poté skonči\n" + +#: pg_dump.c:1001 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 úroveň komprese při použití komprimovaného formátu\n" + +#: pg_dump.c:1002 pg_dumpall.c:624 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT selže po uplynutí TIMEOUT čekáním na zámek tabulky\n" + +#: pg_dump.c:1003 pg_dumpall.c:651 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync nečekat než budou změny bezpečně zapsány na disk\n" + +#: pg_dump.c:1004 pg_dumpall.c:625 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help zobraz tuto nápovědu, poté skonči\n" + +#: pg_dump.c:1006 pg_dumpall.c:626 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Přepínače ovlivňující výstup:\n" + +#: pg_dump.c:1007 pg_dumpall.c:627 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only dump pouze dat bez definic databázových objektů\n" + +#: pg_dump.c:1008 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs zahrnout \"large objects\" do dumpu\n" + +#: pg_dump.c:1009 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs nezahrnovat \"large objects\" do dumpu\n" + +#: pg_dump.c:1010 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean odstranit (drop) databázi před jejím vytvořením\n" + +#: pg_dump.c:1011 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create zahrnout příkazy pro vytvoření databáze do dumpu\n" + +#: pg_dump.c:1012 pg_dumpall.c:629 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=KÓDOVÁNÍ kódování znaků databáze\n" + +#: pg_dump.c:1013 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr "" +" -n, --schema=PATTERN vytvořit dump pouze specifikovaného schématu\n" +"\n" + +#: pg_dump.c:1014 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN nedumpuj uvedená schéma(ta)\n\n" + +#: pg_dump.c:1015 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner nevypisovat příkazy pro nastavení vlastníka objektu\n" +" v čistě textovém formátu\n" + +#: pg_dump.c:1017 pg_dumpall.c:633 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr "" +" -s, --schema-only dump pouze definic databázových objektů\n" +" (tabulek apod.) bez dat\n" + +#: pg_dump.c:1018 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=JMÉNO uživatelské jméno superuživatele použité při dumpu\n" + +#: pg_dump.c:1019 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr "" +" -t, --table=PATTERN provést dump pouze uvedené tabulky\n" +"\n" + +#: pg_dump.c:1020 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr "" +" -T, --exclude-table=PATTERN neprováděj dump uvedených tabulek\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:636 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges neprovádět dump přístupových práv (grant/revoke)\n" + +#: pg_dump.c:1022 pg_dumpall.c:637 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade pouze pro použití upgradovacími nástroji\n" + +#: pg_dump.c:1023 pg_dumpall.c:638 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts použije pro dump dat příkaz INSERT se jmény sloupců\n" + +#: pg_dump.c:1024 pg_dumpall.c:639 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr "" +" --disable-dollar-quoting nepoužívat znak dolaru místo uvozovek, používat\n" +" standardní SQL uvozování\n" + +#: pg_dump.c:1025 pg_dumpall.c:640 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers zakázat volání triggerů během obnovy dat\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security povolit row security (vypíše pouze data ke kterým má\n" +" uživatel přístup)\n" + +#: pg_dump.c:1028 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=VZOR nedumpuj data pro zadané tabulky\n\n" + +#: pg_dump.c:1029 pg_dumpall.c:642 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM přenastav výchozí nastavení pro extra_float_digits\n" + +#: pg_dump.c:1030 pg_dumpall.c:643 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists použít IF EXISTS při mazání objektů\n" + +#: pg_dump.c:1031 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=PATTERN\n" +" zahrne data z foreign tabulek náležících k foreign\n" +" serverům odpovídajícím PATTERN\n" + +#: pg_dump.c:1034 pg_dumpall.c:644 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts použít pro dump dat příkazy INSERT místo COPY\n" + +#: pg_dump.c:1035 pg_dumpall.c:645 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root data do partition tabulek načítat přes root tabulku\n" + +#: pg_dump.c:1036 pg_dumpall.c:646 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments neprovádět dump komentářů\n" + +#: pg_dump.c:1037 pg_dumpall.c:647 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications neprovádět dump publikací\n" + +#: pg_dump.c:1038 pg_dumpall.c:649 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels neprovádět dump bezpečnostních štítků\n" + +#: pg_dump.c:1039 pg_dumpall.c:650 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions neprovádět dump subsckripcí\n" + +#: pg_dump.c:1040 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots nepoužívat synchronizované snapshoty v paralelních jobech\n" + +#: pg_dump.c:1041 pg_dumpall.c:652 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces neprovádět dump přiřazení tablespaces\n" + +#: pg_dump.c:1042 pg_dumpall.c:653 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data nedumpuj data unlogged tabulek\n" + +#: pg_dump.c:1043 pg_dumpall.c:654 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing přidej ON CONFLICT DO NOTHING do INSERT příkazů\n" + +#: pg_dump.c:1044 pg_dumpall.c:655 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers všechny identifikátory uveď v uvozovkách, i když se nejedná o klíčová slova\n" + +#: pg_dump.c:1045 pg_dumpall.c:656 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS počet řádek per INSERT; implikuje --inserts\n" + +#: pg_dump.c:1046 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION dump pojmenované sekce (pre-data, data, nebo post-data)\n" + +#: pg_dump.c:1047 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable počkej než bude možné provést dump bez anomálií\n" + +#: pg_dump.c:1048 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT pro dump použít zadaný snapshot\n" + +#: pg_dump.c:1049 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names vyžadovat aby každý vzor pro zahrnutí tabulek a/nebo schémat\n" +" odpovídal alespoň jednomu objektu\n" + +#: pg_dump.c:1051 pg_dumpall.c:657 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" používat příkaz SET SESSION AUTHORIZATION namísto\n" +" příkazu ALTER OWNER pro nastavení vlastníka\n" + +#: pg_dump.c:1055 pg_dumpall.c:661 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Volby spojení:\n" + +#: pg_dump.c:1056 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=JMÉNO jméno zdrojové databáze\n" + +#: pg_dump.c:1057 pg_dumpall.c:663 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME host databázového serveru nebo adresář se sockety\n" + +#: pg_dump.c:1058 pg_dumpall.c:665 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT port databázového serveru\n" + +#: pg_dump.c:1059 pg_dumpall.c:666 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=JMÉNO připoj se jako uvedený uživatel\n" + +#: pg_dump.c:1060 pg_dumpall.c:667 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password nikdy se neptej na heslo\n" + +#: pg_dump.c:1061 pg_dumpall.c:668 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password zeptej se na heslo (mělo by se dít automaticky)\n" + +#: pg_dump.c:1062 pg_dumpall.c:669 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME před dumpem proveď SET ROLE\n" + +#: pg_dump.c:1064 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Není-li specifikováno jméno databáze, použije se proměnná prostředí\n" +"PGDATABASE.\n" +"\n" + +#: pg_dump.c:1066 pg_dumpall.c:673 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Chyby hlašte na <%s>.\n" + +#: pg_dump.c:1067 pg_dumpall.c:674 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s domácí stránka: <%s>\n" + +#: pg_dump.c:1086 pg_dumpall.c:499 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "specifikováno neplatné klientské kódování \"%s\"" + +#: pg_dump.c:1235 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synchronizované snapshoty nejsou na této verzi serveru podporovány.\n" +"Pokud nepotřebujete synchronizované snapshoty, použijte přepínač\n" +"--no-synchronized-snapshots." + +#: pg_dump.c:1304 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "specifikován neplatný formát \"%s\" výstupu" + +#: pg_dump.c:1342 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "nebyla nalezena žádná schémata odpovídající vzoru \"%s\"" + +#: pg_dump.c:1389 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "nebyly nalezeny žádné foreign servery odpovídající vzoru \"%s\"" + +#: pg_dump.c:1452 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "nebyla nalezena žádná tabulka odpovídající vzoru \"%s\"" + +#: pg_dump.c:1865 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "dumpuji obsah tabulky \"%s.%s\"" + +#: pg_dump.c:1972 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Dumpování obsahu tabulky \"%s\" selhalo: volání PQgetCopyData() selhalo." + +#: pg_dump.c:1973 pg_dump.c:1983 +#, c-format +msgid "Error message from server: %s" +msgstr "Chybová zpráva ze serveru: %s" + +#: pg_dump.c:1974 pg_dump.c:1984 +#, c-format +msgid "The command was: %s" +msgstr "Příkaz byl: %s" + +#: pg_dump.c:1982 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Dumpování obsahu tabulky \"%s\" selhalo: volání PQgetResult() selhalo." + +#: pg_dump.c:2742 +#, c-format +msgid "saving database definition" +msgstr "ukládám definice databáze" + +#: pg_dump.c:3214 +#, c-format +msgid "saving encoding = %s" +msgstr "ukládám kódování znaků = %s" + +#: pg_dump.c:3239 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "ukládám standard_conforming_strings = %s" + +#: pg_dump.c:3278 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "nelze zpracovat výsledek current_schemas()" + +#: pg_dump.c:3297 +#, c-format +msgid "saving search_path = %s" +msgstr "ukládám search_path = %s" + +#: pg_dump.c:3337 +#, c-format +msgid "reading large objects" +msgstr "čtu \"large objects\"" + +#: pg_dump.c:3519 +#, c-format +msgid "saving large objects" +msgstr "ukládám \"large objects\"" + +#: pg_dump.c:3565 +#, c-format +msgid "error reading large object %u: %s" +msgstr "chyba při čtení large objektu %u: %s" + +#: pg_dump.c:3617 +#, c-format +msgid "reading row security enabled for table \"%s.%s\"" +msgstr "čtu row security enabled pro tabulku \"%s.%s\"" + +#: pg_dump.c:3648 +#, c-format +msgid "reading policies for table \"%s.%s\"" +msgstr "čtu policies pro tablku \"%s.%s\"" + +#: pg_dump.c:3800 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "neočekáváný typ policy příkazu: %c" + +#: pg_dump.c:3951 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "vlastník publikace \"%s\" se zdá být neplatný" + +#: pg_dump.c:4096 +#, c-format +msgid "reading publication membership for table \"%s.%s\"" +msgstr "čtu členství v publikacích pro tabulku \"%s.%s\"" + +#: pg_dump.c:4239 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "subscriptions nejsou zahrnuty do dumpu protože aktuální uživatel není superuživatl" + +#: pg_dump.c:4293 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "vlastník subskripce \"%s\" se zdá být neplatný" + +#: pg_dump.c:4337 +#, c-format +msgid "could not parse subpublications array" +msgstr "nelze naparsovat pole \"subpublications\"" + +#: pg_dump.c:4659 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "nelze najít nadřízené rozšíření pro %s %s" + +#: pg_dump.c:4791 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "vlastník schématu \"%s\" se zdá být neplatný" + +#: pg_dump.c:4814 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "schéma s OID %u neexistuje" + +#: pg_dump.c:5139 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "vlastník datového typu \"%s\" se zdá být neplatný" + +#: pg_dump.c:5224 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "vlastník operátoru \"%s\" se zdá být neplatný" + +#: pg_dump.c:5526 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "vlastník třídy operátorů \"%s\" se zdá být neplatný" + +#: pg_dump.c:5610 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "vlastník rodiny operátorů \"%s\" se zdá být neplatný" + +#: pg_dump.c:5779 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "vlastník agregační funkce \"%s\" se zdá být neplatný" + +#: pg_dump.c:6039 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "vlastník funkce \"%s\" se zdá být neplatný" + +#: pg_dump.c:6867 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "vlastník tabulky \"%s\" se zdá být neplatný" + +#: pg_dump.c:6909 pg_dump.c:17389 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "selhala kontrola, OID %u rodičovské tabulky u sekvence s OID %u nelze najít" + +#: pg_dump.c:7051 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "čtu indexy pro tabulku \"%s.%s\"" + +#: pg_dump.c:7466 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "čtu cizí klíče pro tabulku \"%s.%s\"" + +#: pg_dump.c:7747 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "selhala kontrola, OID %u rodičovské tabulky u pg_rewrite položky OID %u nelze najít" + +#: pg_dump.c:7830 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "čtu triggery pro tabulku \"%s.%s\"" + +#: pg_dump.c:7963 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "dotaz vrátil prázdné jméno referencované tabulky pro trigger \"%s\" cizího klíče pro tabulku \"%s\" (OID tabulky: %u)" + +#: pg_dump.c:8518 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "hledám sloupce a typy pro tabulku \"%s.%s\"" + +#: pg_dump.c:8654 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "neplatné číslování sloupců v tabulce \"%s\"" + +#: pg_dump.c:8691 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "hledám DEFAULT výrazy pro tabulku \"%s.%s\"" + +#: pg_dump.c:8713 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "neplatná \"adnum\" hodnota %d pro tabulku \"%s\"" + +#: pg_dump.c:8778 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "hledám CHECK omezení pro tabulku \"%s.%s\"" + +#: pg_dump.c:8827 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "očekáván %d check constraint na tabulce \"%s\" nalezeno %d" +msgstr[1] "očekávány %d check constrainty na tabulce \"%s\" nalezeno %d" +msgstr[2] "očekáváno %d check constraintů na tabulce \"%s\" nalezeno %d" + +#: pg_dump.c:8831 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Systémové katalogy mohou být poškozeny.)" + +#: pg_dump.c:10417 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "typtype datového typu \"%s\" se zdá být neplatný" + +#: pg_dump.c:11771 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "nesmyslná hodnota v \"proargmodes\" poli" + +#: pg_dump.c:12143 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "nelze naparsovat pole \"proallargtypes\"" + +#: pg_dump.c:12159 +#, c-format +msgid "could not parse proargmodes array" +msgstr "nelze naparsovat pole \"proargmodes\"" + +#: pg_dump.c:12173 +#, c-format +msgid "could not parse proargnames array" +msgstr "nelze naparsovat pole \"proargnames\"" + +#: pg_dump.c:12184 +#, c-format +msgid "could not parse proconfig array" +msgstr "nelze naparsovat pole \"proconfig\"" + +#: pg_dump.c:12264 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "nerozpoznaná \"provolatile\" hodnota pro funkci \"%s\"" + +#: pg_dump.c:12314 pg_dump.c:14372 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "nerozpoznaná proparallel\" hodnota pro funkci \"%s\"" + +#: pg_dump.c:12453 pg_dump.c:12562 pg_dump.c:12569 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "nelze najít definici pro funkci ID %u" + +#: pg_dump.c:12492 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "chybná hodnota v položce pg_cast.castfunc nebo pg_cast.castmethod" + +#: pg_dump.c:12495 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "nesmyslná hodnota v položce \"pg_cast.castmethod\"" + +#: pg_dump.c:12588 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "chybná definice transformace, alespoň jedno z trffromsql a trftosql by mělo být nenulové" + +#: pg_dump.c:12605 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "nesmyslná hodnota v položce pg_transform.trffromsql" + +#: pg_dump.c:12626 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "nesmyslná hodnota v položce pg_transform.trftosql" + +#: pg_dump.c:12942 +#, c-format +msgid "could not find operator with OID %s" +msgstr "nelze najít operátor s OID %s" + +#: pg_dump.c:13010 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "neplatný typ \"%c\" access metody \"%s\"" + +#: pg_dump.c:13764 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "neočekávaný poskytovatel collation: %s" + +#: pg_dump.c:14236 +#, c-format +msgid "aggregate function %s could not be dumped correctly for this database version; ignored" +msgstr "agregační funkci %s nelze dumpovat korektně pro tuto verzi databáze; ignorováno" + +#: pg_dump.c:14291 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "neznámá aggfinalmodify hodnota for agregační funkci \"%s\"" + +#: pg_dump.c:14347 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "neznámá aggmfinalmodify hodnota for agregační funkci \"%s\"" + +#: pg_dump.c:15069 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "neznámý typ objektu (%d) ve výchozích privilegiích" + +#: pg_dump.c:15087 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "nelze zpracovat seznam oprávnění ACL (%s)" + +#: pg_dump.c:15172 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "nelze zpracovat výchozí GRANT ACL seznam (%s) nebo výchozí REVOKE ACL seznam (%s) pro objekt \"%s\" (%s)" + +#: pg_dump.c:15180 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "nelze zpracovat GRANT ACL seznam (%s) nebo REVOKE ACL seznam (%s) pro objekt \"%s\" (%s)" + +#: pg_dump.c:15695 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "dotaz na získání definice view \"%s\" nevrátil žádná data" + +#: pg_dump.c:15698 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "dotaz na získání definice view \"%s\" vrátil více jak jednu definici" + +#: pg_dump.c:15705 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "definice view \"%s\" se zdá být prázdná (nulová délka)" + +#: pg_dump.c:15789 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS již není podporováno (tabulka \"%s\")" + +#: pg_dump.c:16269 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "neplatný počet rodičů %d pro tabulku \"%s\"" + +#: pg_dump.c:16592 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "neplatné číslo sloupce %d pro tabulku \"%s\"" + +#: pg_dump.c:16877 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "chybí index pro omezení \"%s\"" + +#: pg_dump.c:17102 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "neočekávaný typ omezení: %c" + +#: pg_dump.c:17234 pg_dump.c:17454 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "dotaz pro načtení dat sekvence \"%s\" vrátil %d řádek (expected 1)" +msgstr[1] "dotaz pro načtení dat sekvence \"%s\" vrátil %d řádky (expected 1)" +msgstr[2] "dotaz pro načtení dat sekvence \"%s\" vrátil %d řádek (expected 1)" + +#: pg_dump.c:17268 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "neočekávaný typ sekvence: %s" + +#: pg_dump.c:17552 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "neočekávaná hodnota tgtype: %d" + +#: pg_dump.c:17626 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "neplatný řetězec argumentů (%s) pro trigger \"%s\" tabulky \"%s\"" + +#: pg_dump.c:17862 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "dotaz k získání pravidla (RULE) \"%s\" pro tabulku \"%s\" selhal: vrácen chybný počet řádků" + +#: pg_dump.c:18024 +#, c-format +msgid "could not find referenced extension %u" +msgstr "nelze najít odkazované rozšíření %u" + +#: pg_dump.c:18236 +#, c-format +msgid "reading dependency data" +msgstr "čtu data o závislostech" + +#: pg_dump.c:18329 +#, c-format +msgid "no referencing object %u %u" +msgstr "žádný odkazující objekt %u: %u" + +#: pg_dump.c:18340 +#, c-format +msgid "no referenced object %u %u" +msgstr "žádný odkazovaný objekt %u: %u" + +#: pg_dump.c:18713 +#, c-format +msgid "could not parse reloptions array" +msgstr "nelze naparsovat pole \"reloptions\"" + +#: pg_dump_sort.c:360 +#, c-format +msgid "invalid dumpId %d" +msgstr "neplatné dumpId %d" + +#: pg_dump_sort.c:366 +#, c-format +msgid "invalid dependency %d" +msgstr "neplatná závislost %d" + +#: pg_dump_sort.c:599 +#, c-format +msgid "could not identify dependency loop" +msgstr "nelze identifikovat smyčku závislostí" + +#: pg_dump_sort.c:1170 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "na této tabulce existuje cyklus cizích klíčů:" +msgstr[1] "mezi těmito tabulkami existuje cyklus cizích klíčů:" +msgstr[2] "mezi těmito tabulkami existuje cyklus cizích klíčů:" + +#: pg_dump_sort.c:1174 pg_dump_sort.c:1194 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1175 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Bez zadání volby --disable-triggers nebo dočasného vypnutí constraintů zřejmě nebudete schopni tento dump obnovit." + +#: pg_dump_sort.c:1176 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Zvažte použití kompletního (full) dumpu namísto --data-only dumpu pro odstranění tohoto problému." + +#: pg_dump_sort.c:1188 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "nelze vyřešit smyčku závislostí mezi těmito položkami:" + +#: pg_dumpall.c:199 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Program \"%s\" je vyžadován aplikací %s, ale nebyl nalezen ve stejném\n" +"adresáři jako \"%s\".\n" +"Zkontrolujte vaši instalaci." + +#: pg_dumpall.c:204 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Program \"%s\" byl nalezen pomocí \"%s\",\n" +"ale nebyl ve stejné verzi jako %s.\n" +"Zkontrolujte vaši instalaci." + +#: pg_dumpall.c:356 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "volba --exclude-database nemůže být použita společně s -g/--globals-only, -r/--roles-only, nebo -t/--tablespaces-only" + +#: pg_dumpall.c:365 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "volby -g/--globals-only a -r/--roles-only nelze používat společně" + +#: pg_dumpall.c:373 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "volby -g/--globals-only a -t/--tablespaces-only nelze používat společně" + +#: pg_dumpall.c:387 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "volby -r/--roles-only a -t/--tablespaces-only nelze používat společně" + +#: pg_dumpall.c:448 pg_dumpall.c:1754 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "nelze navázat spojení s databází \"%s\"" + +#: pg_dumpall.c:462 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"nelze navázat spojení s databází \"postgres\" nebo \"template1\"\n" +"Zadejte prosím alternativní databázi." + +#: pg_dumpall.c:616 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s extrahuje PostgreSQL databázi do souboru s SQL skriptem.\n" +"\n" + +#: pg_dumpall.c:618 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [VOLBA]...\n" + +#: pg_dumpall.c:621 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=SOUBOR výstupní soubor\n" + +#: pg_dumpall.c:628 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean odstranit (drop) databázi před jejím vytvořením\n" + +#: pg_dumpall.c:630 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only dump pouze globálních objektů, ne databáze\n" + +#: pg_dumpall.c:631 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner nevypisuje příkazy k nastavení vlastníka objektů\n" + +#: pg_dumpall.c:632 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only dump pouze rolí, ne databází nebo tablespaců\n" + +#: pg_dumpall.c:634 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=JMÉNO uživatelské jméno superuživatele použité při dumpu\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only dump pouze tablespaců, ne databází nebo rolí\n" + +#: pg_dumpall.c:641 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=VZOR nedumpuj databáze jejichž jména odpovídají VZORu\n" + +#: pg_dumpall.c:648 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords hesla pro role nezahrnovat do dumpu\n" + +#: pg_dumpall.c:662 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR specifikace připojení do databáze\n" + +#: pg_dumpall.c:664 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME alternativní výchozí databáze\n" + +#: pg_dumpall.c:671 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Pokud není použito -f/--file, potom SQL skript bude vypsán přímo na standardní\n" +"výstup.\n" +"\n" + +#: pg_dumpall.c:877 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "název role začínající s \"pg_\" přeskočen (%s)" + +#: pg_dumpall.c:1278 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "nelze zpracovat ACL seznam (%s) pro prostor tabulek \"%s\"" + +#: pg_dumpall.c:1495 +#, c-format +msgid "excluding database \"%s\"" +msgstr "nedumpuji databázi \"%s\"" + +#: pg_dumpall.c:1499 +#, c-format +msgid "dumping database \"%s\"" +msgstr "dumpuji databázi \"%s\"" + +#: pg_dumpall.c:1531 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump selhal při zpracovávání databáze \"%s\", ukončuji se" + +#: pg_dumpall.c:1540 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "nelze otevřít logovací soubor \"%s\": %m" + +#: pg_dumpall.c:1584 +#, c-format +msgid "running \"%s\"" +msgstr "běží \"%s\"" + +#: pg_dumpall.c:1775 +#, c-format +msgid "could not connect to database \"%s\": %s" +msgstr "nelze navázat spojení s databází \"%s\": %s" + +#: pg_dumpall.c:1805 +#, c-format +msgid "could not get server version" +msgstr "nelze získat verzi serveru" + +#: pg_dumpall.c:1811 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "nelze zpracovat verzi serveru \"%s\"" + +#: pg_dumpall.c:1883 pg_dumpall.c:1906 +#, c-format +msgid "executing %s" +msgstr "spouštím: %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "musí být specifikována jedna z voleb -d/--dbname a -f/--file" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "volby -d/--dbname a -f/--file nelze používat společně" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "volby -C/--create a -1/--single-transaction nelze používat společně" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "maximální počet paralelních jobů je %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "nelze zadat --single-transaction a několik úloh" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "neznámý formát archivu \"%s\"; zadejte prosím \"c\", \"d\" nebo \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "chyby ignorovány při obnovení: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s obnovuje PostgreSQL databázi z archivu vytvořeného pomocí pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [PŘEPÍNAČ]... [SOUBOR]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=JMÉNO jméno cílové databáze\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=SOUBOR výstupní soubor (- pro stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t formát záložního souboru (měl by být automatický)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list zobrazit sumarizovaný obsah (TOC) archivu\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose vypisovat více informací\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version zobraz informaci o verzi, poté skonči\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help zobraz tuto nápovědu, poté skonči\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Přepínače ovlivňující obnovu:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only obnovit pouze data, ne definice databázových objektů\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create vypíše příkazy pro vytvoření databáze\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error ukončit při chybě, implicitně pokračuje\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=JMÉNO obnovit jmenovaný index\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM použij pro obnovu daný počet paralelních jobů\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=SOUBOR použít specifikovaný obsah (TOC) pro řazení\n" +" výstupu z tohoto souboru\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME obnovit pouze objekty v tomto schématu\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME neobnovovat objekty v tomto schématu\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr "" +" -P, --function=JMÉNO(args)\n" +" obnovit funkci daného jména\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only obnovit pouze definice objektů, bez dat\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr "" +" -S, --superuser=JMÉNO jméno superuživatele použité pro\n" +" zakázaní triggerů\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=JMÉNO obnovit pouze jmenovanou relaci (tabulka, pohled, etc.)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=JMÉNO obnovit pouze jmenovaný trigger\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges přeskočit obnovu přístupových práv (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr "" +" -1, --single-transaction\n" +" zpracuj soubor v rámci jedné transakce\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security povolit row security\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments neobnovovat komentáře\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables\n" +" neobnovuj data tabulek které nemohly být vytvořeny\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications do not restore publications\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels neobnovuj bezpečnostní štítky\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions neobnovovat subskripce\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces neobnovuj přiřazení tablespaces\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION obnov pojmenovanou sekci (pre-data, data, nebo post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME před obnovou proveď SET ROLE\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Volby -I, -n, -N, -P, -t, -T, a --section mohou být kombinovány a zadány několikrát\n" +"pro výběr více objektů.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Není-li definován vstupní soubor, je použit standardní vstup.\n" +"\n" + +#~ msgid "could not read symbolic link \"%s\"" +#~ msgstr "nelze číst symbolický link \"%s\"" + +#~ msgid "child process was terminated by signal %s" +#~ msgstr "potomek byl ukončen signálem %s" + +#~ msgid "compress_io" +#~ msgstr "compress_io" + +#~ msgid "parallel archiver" +#~ msgstr "paralelní archivář" + +#~ msgid "archiver" +#~ msgstr "archivář" + +#~ msgid "-C and -1 are incompatible options\n" +#~ msgstr "-C a -1 jsou nekompatibilní přepínače\n" + +#~ msgid "attempting to ascertain archive format\n" +#~ msgstr "pokouším se zjistit formát archivu\n" + +#~ msgid "allocating AH for %s, format %d\n" +#~ msgstr "alokován AH pro %s, formát %d\n" + +#~ msgid "read TOC entry %d (ID %d) for %s %s\n" +#~ msgstr "přečetl jsem TOC záznam %d (ID %d) pro %s %s\n" + +#~ msgid "could not set default_with_oids: %s" +#~ msgstr "nelze nastavit default_with_oids: %s" + +#~ msgid "entering restore_toc_entries_prefork\n" +#~ msgstr "vstupuji do restore_toc_entries_prefork\n" + +#~ msgid "entering restore_toc_entries_parallel\n" +#~ msgstr "vstupuji do restore_toc_entries_parallel\n" + +#~ msgid "entering restore_toc_entries_postfork\n" +#~ msgstr "vstupuji do restore_toc_entries_postfork\n" + +#~ msgid "no item ready\n" +#~ msgstr "žádná položka není připravena\n" + +#~ msgid "transferring dependency %d -> %d to %d\n" +#~ msgstr "přenáším závislost %d -> %d to %d\n" + +#~ msgid "reducing dependencies for %d\n" +#~ msgstr "redukuji závislosti pro %d\n" + +#~ msgid "custom archiver" +#~ msgstr "vlastní archivář" + +#~ msgid "archiver (db)" +#~ msgstr "archivář (db)" + +#~ msgid "failed to reconnect to database\n" +#~ msgstr "selhalo znovunavázání spojení s databází\n" + +#~ msgid "failed to connect to database\n" +#~ msgstr "selhalo spojení s databází\n" + +#~ msgid "directory archiver" +#~ msgstr "directory archiver" + +#~ msgid "tar archiver" +#~ msgstr "tar archivář" + +#~ msgid "moving from position %s to next member at file position %s\n" +#~ msgstr "přecházím z pozice %s na následujícího položky na pozici souboru %s\n" + +#~ msgid "now at file position %s\n" +#~ msgstr "nyní na pozici souboru %s\n" + +#~ msgid "skipping tar member %s\n" +#~ msgstr "přeskakován tar člen %s\n" + +#~ msgid "TOC Entry %s at %s (length %s, checksum %d)\n" +#~ msgstr "TOC položka %s na %s (délka %s, kontrolní součet %d)\n" + +#~ msgid "options --inserts/--column-inserts and -o/--oids cannot be used together\n" +#~ msgstr "volby --inserts/--column-inserts a -o/--oids nelze používat společně\n" + +#~ msgid "(The INSERT command cannot set OIDs.)\n" +#~ msgstr "(Příkaz INSERT nemůže nastavovat OID.)\n" + +#~ msgid " -o, --oids include OIDs in dump\n" +#~ msgstr " -o, --oids zahrnout OID do dumpu\n" + +#~ msgid "WARNING: could not parse reloptions array\n" +#~ msgstr "VAROVÁNÍ: nelze naparsovat pole reloptions\n" + +#~ msgid "sorter" +#~ msgstr "sorter" + +#~ msgid " %s\n" +#~ msgstr " %s\n" + +#~ msgid "%s: option --if-exists requires option -c/--clean\n" +#~ msgstr "%s: volba --if-exists vyžaduje volbu -c/--clean\n" + +#~ msgid "%s: could not open the output file \"%s\": %s\n" +#~ msgstr "%s: nelze otevřít výstupní soubor \"%s\": %s\n" + +#~ msgid "%s: invalid client encoding \"%s\" specified\n" +#~ msgstr "%s: specifikováno neplatné klientské kódování \"%s\"\n" + +#~ msgid "%s: executing %s\n" +#~ msgstr "%s: vykonávám %s\n" + +#~ msgid "%s: query failed: %s" +#~ msgstr "%s: dotaz selhal: %s" + +#~ msgid "%s: query was: %s\n" +#~ msgstr "%s: dotaz byl: %s\n" + +#~ msgid "%s: options -s/--schema-only and -a/--data-only cannot be used together\n" +#~ msgstr "%s: volby -s/--schema-only a -a/--data-only nelze použít najednou\n" + +#~ msgid "%s: options -c/--clean and -a/--data-only cannot be used together\n" +#~ msgstr "%s: volby -c/--clean a -a/--data-only nelze používat společně\n" + +#~ msgid "%s: invalid number of parallel jobs\n" +#~ msgstr "%s: neplatný počet paralelních jobů\n" + +#~ msgid "worker is terminating\n" +#~ msgstr "worker končí\n" + +#~ msgid "error processing a parallel work item\n" +#~ msgstr "chyba při paralelním zpracovávání položky\n" + +#~ msgid "terminated by user\n" +#~ msgstr "ukončeno uživatelem\n" + +#~ msgid "setting owner and privileges for %s %s\n" +#~ msgstr "nastavuji vlastníka a přístupová práva pro %s %s\n" + +#~ msgid "could not write to custom output routine\n" +#~ msgstr "nelze zapsat do vlastní výstupní rutiny\n" + +#~ msgid "unexpected end of file\n" +#~ msgstr "neočekávaný konec souboru\n" + +#~ msgid "could not find slot of finished worker\n" +#~ msgstr "nelze najít slot ukončeného workera\n" + +#~ msgid "could not write byte: %s\n" +#~ msgstr "nelze zapsat byte: %s\n" + +#~ msgid "could not write byte\n" +#~ msgstr "nelze zapsat byte\n" + +#~ msgid "could not write null block at end of tar archive\n" +#~ msgstr "nelze zapsat null blok na konec tar archivu\n" + +#~ msgid "archive member too large for tar format\n" +#~ msgstr "položka archivu je příliš velká pro formát tar\n" + +#~ msgid "could not output padding at end of tar member\n" +#~ msgstr "nelze zapsat vycpávku (padding) na konec položky taru\n" + +#~ msgid "mismatch in actual vs. predicted file position (%s vs. %s)\n" +#~ msgstr "aktuální a předpokládaná pozice souboru se neshodují (%s vs. %s)\n" + +#~ msgid "could not open output file \"%s\" for writing\n" +#~ msgstr "nelze otevřít výstupní soubor \"%s\" pro zápis\n" + +#~ msgid "server version must be at least 7.3 to use schema selection switches\n" +#~ msgstr "verze serveru musí být alespoň 7.3 pro použití přepínačů prů výběr schématu\n" + +#~ msgid "query to get data of sequence \"%s\" returned name \"%s\"\n" +#~ msgstr "dotaz na získání dat sekvence \"%s\" vrátil jméno \"%s\"\n" + +#~ msgid "%s: could not parse ACL list (%s) for database \"%s\"\n" +#~ msgstr "%s: nelze zpracovat ACL seznam (%s) pro databázi \"%s\"\n" + +#~ msgid "worker process crashed: status %d\n" +#~ msgstr "worker proces selhal: status %d\n" + +#~ msgid "parallel_restore should not return\n" +#~ msgstr "parallel_restore by neměl skončit\n" + +#~ msgid "could not create worker thread: %s\n" +#~ msgstr "nelze vytvořit worker thread: %s\n" + +#~ msgid "could not parse version string \"%s\"\n" +#~ msgstr "neplatný formát řetězce s verzí \"%s\"\n" + +#~ msgid "%s: could not parse version \"%s\"\n" +#~ msgstr "%s: nelze zpracovat verzi serveru \"%s\"\n" + +#~ msgid "-C and -c are incompatible options\n" +#~ msgstr "-C a -c jsou nekompatibilní přepínače\n" + +#~ msgid "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n" +#~ msgstr "neplatný COPY příkaz -- nelze najít \"copy\" v řetězci \"%s\"\n" + +#~ msgid "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n" +#~ msgstr "neplatný COPY příkaz -- nelze najít \"from stdin\" v řetězci \"%s\" začínající na pozici %lu\n" + +#~ msgid "cannot create directory %s, it exists already\n" +#~ msgstr "nelze vytvořit adresář %s, již existuje\n" + +#~ msgid "cannot create directory %s, a file with this name exists already\n" +#~ msgstr "nelze vytvořit adresář %s, soubor s tímto jménem již existuje\n" + +#~ msgid "path name too long: %s" +#~ msgstr "cesta příliš dlouhá: %s" + +#~ msgid "restoring large object OID %u\n" +#~ msgstr "obnovuji \"large object\" s OID %u\n" + +#~ msgid "options -s/--schema-only and -a/--data-only cannot be used with --section\n" +#~ msgstr "volby -s/--schema-only a -a/--data-only nelze použít s --section\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help ukáže tento text a skončí\n" + +#~ msgid " --version output version information, then exit\n" +#~ msgstr " --version ukáže informace o verzi a skončí\n" + +#~ msgid "%s: options -s/--schema-only and -a/--data-only cannot be used with --section\n" +#~ msgstr "%s: volby -s/--schema-only a -a/--data-only nelze použít s --section\n" + +#~ msgid " -c, --clean clean (drop) database objects before recreating\n" +#~ msgstr " -c, --clean odstranit (drop) databázi před jejím vytvořením\n" + +#~ msgid " -O, --no-owner skip restoration of object ownership\n" +#~ msgstr " -O, --no-owner přeskoč nastavení vlastníka objektů\n" + +#~ msgid " --disable-triggers disable triggers during data-only restore\n" +#~ msgstr " --disable-triggers zakázat volání triggerů během obnovy dat\n" + +#~ msgid "" +#~ " --use-set-session-authorization\n" +#~ " use SET SESSION AUTHORIZATION commands instead of\n" +#~ " ALTER OWNER commands to set ownership\n" +#~ msgstr "" +#~ " --use-set-session-authorization\n" +#~ " používat příkaz SET SESSION AUTHORIZATION namísto\n" +#~ " příkazu ALTER OWNER pro nastavení vlastníka\n" + +#~ msgid "" +#~ "The program \"pg_dump\" was found by \"%s\"\n" +#~ "but was not the same version as %s.\n" +#~ "Check your installation." +#~ msgstr "" +#~ "Program \"pg_dump\" byl nalezen \"%s\",\n" +#~ "který ale není stejné verze jako %s.\n" +#~ "Zkontrolujte vaši instalaci." + +#~ msgid "" +#~ "The program \"pg_dump\" is needed by %s but was not found in the\n" +#~ "same directory as \"%s\".\n" +#~ "Check your installation." +#~ msgstr "" +#~ "Program \"pg_dump\" je potřebný pro %s, ale nebyl nalezen ve stejném\n" +#~ "adresáři jako \"%s\".\n" +#~ "Zkontrolujte vaši instalaci." + +#~ msgid "Report bugs to .\n" +#~ msgstr "Oznámení o chybách zasílejte na .\n" + +#~ msgid "internal error -- neither th nor fh specified in tarReadRaw()" +#~ msgstr "interní chyba -- ani th ani fh nespecifikován v tarReadRaw()" + +#~ msgid "connection needs password" +#~ msgstr "spojení vyžaduje heslo" + +#~ msgid "could not reconnect to database: %s" +#~ msgstr "nelze znovu navázat spojení s databází: %s" + +#~ msgid "could not reconnect to database" +#~ msgstr "nelze znovu navázat spojení s databází" + +#~ msgid "connecting to database \"%s\" as user \"%s\"" +#~ msgstr "připojuji se k databázi \"%s\" jako uživatel \"%s\"" + +#~ msgid "ftell mismatch with expected position -- ftell used" +#~ msgstr "ftell neodpovídá očekávané pozici -- použit ftell" + +#~ msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to lack of data offsets in archive" +#~ msgstr "v archivu nelze najít blok ID %d -- možná kvůli out-of-order restore požadavku, který nemohl být vyřízen kvůli chybějícím datovým offsetům v archivu" diff --git a/src/bin/pg_dump/po/de.po b/src/bin/pg_dump/po/de.po new file mode 100644 index 0000000..ff0c299 --- /dev/null +++ b/src/bin/pg_dump/po/de.po @@ -0,0 +1,2751 @@ +# German message translation file for pg_dump and friends +# Peter Eisentraut , 2001 - 2022. +# +# Use these quotes: »%s« +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-05-06 08:49+0000\n" +"PO-Revision-Date: 2022-05-17 16:42+0200\n" +"Last-Translator: Peter Eisentraut \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "Fatal: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "Fehler: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "Warnung: " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "konnte aktuelles Verzeichnis nicht ermitteln: %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "ungültige Programmdatei »%s«" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "konnte Programmdatei »%s« nicht lesen" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "konnte kein »%s« zum Ausführen finden" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "konnte nicht in Verzeichnis »%s« wechseln: %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "konnte symbolische Verknüpfung »%s« nicht lesen: %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() fehlgeschlagen: %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "Speicher aufgebraucht" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "Speicher aufgebraucht\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "Befehl ist nicht ausführbar" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "Befehl nicht gefunden" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "Kindprozess hat mit Code %d beendet" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "Kindprozess wurde durch Ausnahme 0x%X beendet" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "Kindprozess wurde von Signal %d beendet: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "Kindprozess hat mit unbekanntem Status %d beendet" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "lese Erweiterungen" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "identifiziere Erweiterungselemente" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "lese Schemas" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "lese benutzerdefinierte Tabellen" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "lese benutzerdefinierte Funktionen" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "lese benutzerdefinierte Typen" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "lese prozedurale Sprachen" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "lese benutzerdefinierte Aggregatfunktionen" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "lese benutzerdefinierte Operatoren" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "lese benutzerdefinierte Zugriffsmethoden" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "lese benutzerdefinierte Operatorklassen" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "lese benutzerdefinierte Operatorfamilien" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "lese benutzerdefinierte Textsuche-Parser" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "lese benutzerdefinierte Textsuche-Templates" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "lese benutzerdefinierte Textsuchewörterbücher" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "lese benutzerdefinierte Textsuchekonfigurationen" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "lese benutzerdefinierte Fremddaten-Wrapper" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "lese benutzerdefinierte Fremdserver" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "lese Vorgabeprivilegien" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "lese benutzerdefinierte Sortierfolgen" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "lese benutzerdefinierte Konversionen" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "lese Typumwandlungen" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "lese Transformationen" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "lese Tabellenvererbungsinformationen" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "lese Ereignistrigger" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "finde Erweiterungstabellen" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "finde Vererbungsbeziehungen" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "lese Spalteninfo für interessante Tabellen" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "markiere vererbte Spalten in abgeleiteten Tabellen" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "lese Indexe" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "markiere Indexe in partitionierten Tabellen" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "lese erweiterte Statistiken" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "lese Constraints" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "lese Trigger" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "lese Umschreiberegeln" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "lese Policies" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "lese Publikationen" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "lese Publikationsmitgliedschaft" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "lese Subskriptionen" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "ungültige Anzahl Eltern %d für Tabelle »%s«" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "Sanity-Check fehlgeschlagen, Eltern-OID %u von Tabelle »%s« (OID %u) nicht gefunden" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "konnte numerisches Array »%s« nicht parsen: zu viele Zahlen" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "konnte numerisches Array »%s« nicht parsen: ungültiges Zeichen in Zahl" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "ungültiger Komprimierungscode: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "nicht mit zlib-Unterstützung gebaut" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "konnte Komprimierungsbibliothek nicht initialisieren: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "konnte Komprimierungsstrom nicht schließen: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "konnte Daten nicht komprimieren: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "konnte Daten nicht dekomprimieren: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "konnte Komprimierungsbibliothek nicht schließen: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "konnte nicht aus Eingabedatei lesen: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "konnte nicht aus Eingabedatei lesen: Dateiende" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s() fehlgeschlagen: Fehlercode %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "konnte Kommunikationskanäle nicht erzeugen: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "konnte Arbeitsprozess nicht erzeugen: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "unbekannter Befehl vom Leader-Prozess empfangen: »%s«" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "ungültige Nachricht vom Arbeitsprozess empfangen: »%s«" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"konnte Sperre für Relation »%s« nicht setzen\n" +"Das bedeutet meistens, dass jemand eine ACCESS-EXCLUSIVE-Sperre auf die Tabelle gesetzt hat, nachdem der pg-dump-Elternprozess die anfängliche ACCESS-SHARE-Sperre gesetzt hatte." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "ein Arbeitsprozess endete unerwartet" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "konnte nicht in den Kommunikationskanal schreiben: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: konnte Socket nicht erzeugen: Fehlercode %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: konnte nicht binden: Fehlercode %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: konnte nicht auf Socket hören: Fehlercode %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s() fehlgeschlagen: Fehlercode %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: konnte zweites Socket nicht erzeugen: Fehlercode %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: konnte Socket nicht verbinden: Fehlercode %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: konnte Verbindung nicht annehmen: Fehlercode %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "konnte Ausgabedatei nicht schließen: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "Archivelemente nicht in richtiger Abschnittsreihenfolge" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "unerwarteter Abschnittscode %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "parallele Wiederherstellung wird von diesem Archivdateiformat nicht unterstützt" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "parallele Wiederherstellung wird mit Archiven, die mit pg_dump vor 8.0 erstellt worden sind, nicht unterstützt" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "kann komprimiertes Archiv nicht wiederherstellen (Komprimierung in dieser Installation nicht unterstützt)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "verbinde mit der Datenbank zur Wiederherstellung" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "direkte Datenbankverbindungen sind in Archiven vor Version 1.3 nicht unterstützt" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "implizit werden nur Daten wiederhergestellt" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "entferne %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "konnte nicht bestimmen, wo IF EXISTS in die Anweisung »%s« eingefügt werden soll" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "Warnung aus der ursprünglichen Ausgabedatei: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "erstelle %s »%s.%s«" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "erstelle %s »%s«" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "verbinde mit neuer Datenbank »%s«" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "verarbeite %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "verarbeite Daten für Tabelle »%s.%s«" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "führe %s %s aus" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "schalte Trigger für %s aus" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "schalte Trigger für %s ein" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "interner Fehler -- WriteData kann nicht außerhalb des Kontexts einer DataDumper-Routine aufgerufen werden" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "Large-Object-Ausgabe im gewählten Format nicht unterstützt" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "%d Large Object wiederhergestellt" +msgstr[1] "%d Large Objects wiederhergestellt" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "Wiederherstellung von Large Object mit OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "konnte Large Object %u nicht erstellen: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "konnte Large Object %u nicht öffnen: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "konnte Inhaltsverzeichnisdatei »%s« nicht öffnen: %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "Zeile ignoriert: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "konnte Eintrag für ID %d nicht finden" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "konnte Inhaltsverzeichnisdatei nicht schließen: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "konnte Ausgabedatei »%s« nicht öffnen: %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "konnte Ausgabedatei nicht öffnen: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "%zu Byte Large-Object-Daten geschrieben (Ergebnis = %d)" +msgstr[1] "%zu Bytes Large-Object-Daten geschrieben (Ergebnis = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "konnte Large Object nicht schreiben: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "in Phase INITIALIZING:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "in Phase PROCESSING TOC:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "in Phase FINALIZING:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "in Inhaltsverzeichniseintrag %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "ungültige DumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "ungültige Tabellen-DumpId für »TABLE DATA«-Eintrag" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "unerwartete Datenoffsetmarkierung %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "Dateioffset in Dumpdatei ist zu groß" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "Verzeichnisname zu lang: »%s«" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "Verzeichnis »%s« scheint kein gültiges Archiv zu sein (»toc.dat« existiert nicht)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "konnte Eingabedatei »%s« nicht öffnen: %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "konnte Eingabedatei nicht öffnen: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "konnte Eingabedatei nicht lesen: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "Eingabedatei ist zu kurz (gelesen: %lu, erwartet: 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "Eingabedatei ist anscheinend ein Dump im Textformat. Bitte verwenden Sie psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "Eingabedatei scheint kein gültiges Archiv zu sein (zu kurz?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "Eingabedatei scheint kein gültiges Archiv zu sein" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "konnte Eingabedatei nicht schließen: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "nicht erkanntes Dateiformat »%d«" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "Element %d %s %s abgeschlossen" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "Arbeitsprozess fehlgeschlagen: Code %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "ID %d des Eintrags außerhalb des gültigen Bereichs -- vielleicht ein verfälschtes Inhaltsverzeichnis" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "Wiederherstellung von Tabellen mit WITH OIDS wird nicht mehr unterstützt" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "nicht erkannte Kodierung »%s«" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "ungültiger ENCODING-Eintrag: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "ungültiger STDSTRINGS-Eintrag: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "Schema »%s« nicht gefunden" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "Tabelle »%s« nicht gefunden" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "Index »%s« nicht gefunden" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "Funktion »%s« nicht gefunden" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "Trigger »%s« nicht gefunden" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "konnte Sitzungsbenutzer nicht auf »%s« setzen: %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "konnte search_path nicht auf »%s« setzen: %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "konnte default_tablespace nicht auf »%s« setzen: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "konnte default_table_access_method nicht setzen: %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "kann Eigentümer für Objekttyp »%s« nicht setzen" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "magische Zeichenkette im Dateikopf nicht gefunden" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "nicht unterstützte Version (%d.%d) im Dateikopf" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "Prüfung der Integer-Größe (%lu) fehlgeschlagen" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "Archiv wurde auf einer Maschine mit größeren Integers erstellt; einige Operationen könnten fehlschlagen" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "erwartetes Format (%d) ist nicht das gleiche wie das in der Datei gefundene (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "Archiv ist komprimiert, aber diese Installation unterstützt keine Komprimierung -- keine Daten verfügbar" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "ungültiges Erstellungsdatum im Kopf" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "verarbeite Element %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "Eintritt in Hauptparallelschleife" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "Element %d %s %s wird übersprungen" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "starte Element %d %s %s" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "Hauptparallelschleife beendet" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "verarbeite verpasstes Element %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "Tabelle »%s« konnte nicht erzeugt werden, ihre Daten werden nicht wiederhergestellt werden" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "ungültige OID für Large Object" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "Fehler beim Suchen in Datei: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "Datenblock %d hat falsche Seek-Position" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "unerkannter Datenblocktyp (%d) beim Suchen im Archiv gefunden" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "konnte Block-ID %d nicht im Archiv finden -- möglicherweise wegen Wiederherstellung außer der Reihe, was nicht möglich ist, weil die Eingabedatei kein Suchen unterstützt" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "konnte Block-ID %d nicht im Archiv finden -- möglicherweise beschädigtes Archiv" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "unerwartete Block-ID (%d) beim Lesen der Daten gefunden -- erwartet wurde %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "unerkannter Datenblocktyp %d beim Wiederherstellen des Archivs gefunden" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "konnte nicht aus Eingabedatei lesen: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "konnte Positionszeiger in Archivdatei nicht ermitteln: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "konnte Archivdatei nicht schließen: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "nur Eingabearchive können neu geöffnet werden" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "parallele Wiederherstellung aus der Standardeingabe wird nicht unterstützt" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "parallele Wiederherstellung aus einer Datei, die kein Suchen ermöglicht, wird nicht unterstützt" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "konnte Positionszeiger in Archivdatei nicht setzen: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "Kompressor ist aktiv" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "konnte server_version nicht von libpq ermitteln" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "Version des Servers: %s; Version von %s: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "Abbruch wegen unpassender Serverversion" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "bereits mit einer Datenbank verbunden" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Passwort: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "konnte nicht mit der Datenbank verbinden" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "Wiederverbindung fehlgeschlagen: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "Anfrage fehlgeschlagen: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "Anfrage war: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "Anfrage ergab %d Zeile anstatt einer: %s" +msgstr[1] "Anfrage ergab %d Zeilen anstatt einer: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sDie Anweisung war: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "konnte Anfrage nicht ausführen" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "Fehler in PQputCopyData: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "Fehler in PQputCopyEnd: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY fehlgeschlagen für Tabelle »%s«: %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "unerwartete zusätzliche Ergebnisse während COPY von Tabelle »%s«" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "konnte Datenbanktransaktion nicht starten" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "konnte Datenbanktransaktion nicht beenden" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "kein Ausgabeverzeichnis angegeben" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht lesen: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht schließen: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "konnte nicht in Ausgabedatei schreiben: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "konnte Datendatei nicht schließen: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "konnte Datendatei »%s« nicht schließen: %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "konnte Large-Object-Inhaltsverzeichnisdatei »%s« nicht zur Eingabe öffnen: %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "ungültige Zeile in Large-Object-Inhaltsverzeichnisdatei »%s«: %s" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "Fehler beim Lesen von Large-Object-Inhaltsverzeichnisdatei »%s«" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "konnte Large-Object-Inhaltsverzeichnisdatei »%s« nicht schließen: %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "konnte BLOB-Datendatei nicht schließen: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "konnte nicht in Blobs-Inhaltsverzeichnisdatei schreiben" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "konnte BLOB-Inhaltsverzeichnisdatei nicht schließen: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "Dateiname zu lang: »%s«" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "dieses Format kann nicht gelesen werden" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "konnte Inhaltsverzeichnisdatei »%s« nicht zur Ausgabe öffnen: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "konnte Inhaltsverzeichnisdatei nicht zur Ausgabe öffnen: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "Komprimierung ist im Tar-Format nicht unterstützt" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "konnte Inhaltsverzeichnisdatei »%s« nicht zur Eingabe öffnen: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "konnte Inhaltsverzeichnisdatei nicht zur Eingabe öffnen: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "konnte Datei »%s« nicht im Archiv finden" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "konnte keine temporären Dateinamen erzeugen: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "konnte temporäre Datei nicht öffnen" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "konnte Tar-Mitglied nicht schließen: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "unerwartete Syntax der COPY-Anweisung: »%s«" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "Large Object hat ungültige OID (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "konnte temporäre Datei nicht schließen: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "tatsächliche Dateilänge (%s) stimmt nicht mit erwarteter Länge (%s) überein" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "konnte Kopf für Datei »%s« im Tar-Archiv nicht finden" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "Ausgabe der Daten in anderer Reihenfolge wird in diesem Archivformat nicht unterstützt: »%s« wird benötigt, aber es kommt vor »%s« in der Archivdatei." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "unvollständiger Tar-Dateikopf gefunden (%lu Byte)" +msgstr[1] "unvollständiger Tar-Dateikopf gefunden (%lu Bytes)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "beschädigter Tar-Kopf in %s gefunden (%d erwartet, %d berechnet), Dateiposition %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "unbekannter Abschnittsname: »%s«" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "on_exit_nicely-Slots aufgebraucht" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "Komprimierungsniveau muss im Bereich 0..9 sein" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits muss im Bereich -15..3 sein" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "Zeilen-pro-Insert muss im Bereich %d..%d sein" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "Optionen -s/--schema-only und -a/--data-only können nicht zusammen verwendet werden" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "Optionen -s/--schema-only und --include-foreign-data können nicht zusammen verwendet werden" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "Option --include-foreign-data wird nicht mit paralleler Sicherung unterstützt" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "Optionen -c/--clean und -a/--data-only können nicht zusammen verwendet werden" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "Option --if-exists benötigt Option -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "Option --on-conflict-do-nothing benötigt Option --inserts, --rows-per-insert oder --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "Komprimierung ist in dieser Installation nicht verfügbar -- Archiv wird nicht komprimiert" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "ungültige Anzahl paralleler Jobs" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "parallele Sicherung wird nur vom Ausgabeformat »Verzeichnis« unterstützt" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synchronisierte Snapshots werden von dieser Serverversion nicht unterstützt.\n" +"Verwenden Sie --no-synchronized-snapshots, wenn Sie keine synchronisierten\n" +"Snapshots benötigen." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Exportierte Snapshots werden in dieser Serverversion nicht unterstützt." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "letzte eingebaute OID ist %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "keine passenden Schemas gefunden" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "keine passenden Tabellen gefunden" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "keine passenden Erweiterungen gefunden" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s gibt eine Datenbank als Textdatei oder in anderen Formaten aus.\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Aufruf:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [OPTION]... [DBNAME]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Allgemeine Optionen:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=DATEINAME Name der Ausgabedatei oder des -verzeichnisses\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p Ausgabeformat (custom, d=Verzeichnis, tar,\n" +" plain text)\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM so viele parallele Jobs zur Sicherung verwenden\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose »Verbose«-Modus\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 Komprimierungsniveau für komprimierte Formate\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=ZEIT Abbruch nach ZEIT Warten auf Tabellensperre\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr "" +" --no-sync nicht warten, bis Änderungen sicher auf\n" +" Festplatte geschrieben sind\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Optionen die den Inhalt der Ausgabe kontrollieren:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only nur Daten ausgeben, nicht das Schema\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs Large Objects mit ausgeben\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs Large Objects nicht mit ausgeben\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean Datenbankobjekte vor der Wiedererstellung löschen\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr "" +" -C, --create Anweisungen zum Erstellen der Datenbank in\n" +" Ausgabe einfügen\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=MUSTER nur die angegebene(n) Erweiterung(en) ausgeben\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=KODIERUNG Daten in Kodierung KODIERUNG ausgeben\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=MUSTER nur das/die angegebene(n) Schema(s) ausgeben\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=MUSTER das/die angegebene(n) Schema(s) NICHT ausgeben\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner Wiederherstellung der Objekteigentümerschaft im\n" +" »plain text«-Format auslassen\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only nur das Schema, nicht die Daten, ausgeben\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME Superusername für »plain text«-Format\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=MUSTER nur die angegebene(n) Tabelle(n) ausgeben\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=MUSTER die angegebene(n) Tabelle(n) NICHT ausgeben\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges Zugriffsprivilegien (grant/revoke) nicht ausgeben\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade wird nur von Upgrade-Programmen verwendet\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr "" +" --column-inserts Daten als INSERT-Anweisungen mit Spaltennamen\n" +" ausgeben\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr "" +" --disable-dollar-quoting Dollar-Quoting abschalten, normales SQL-Quoting\n" +" verwenden\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr "" +" --disable-triggers Trigger während der Datenwiederherstellung\n" +" abschalten\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security Sicherheit auf Zeilenebene einschalten (nur Daten\n" +" ausgeben, auf die der Benutzer Zugriff hat)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=MUSTER Daten der angegebenen Tabelle(n) NICHT ausgeben\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=ZAHL Einstellung für extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists IF EXISTS verwenden, wenn Objekte gelöscht werden\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=MUSTER\n" +" Daten von Fremdtabellen auf Fremdservern, die\n" +" mit MUSTER übereinstimmen, mit sichern\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts Daten als INSERT-Anweisungen statt COPY ausgeben\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root Partitionen über die Wurzeltabelle laden\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments Kommentare nicht ausgeben\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications Publikationen nicht ausgeben\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels Security-Label-Zuweisungen nicht ausgeben\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions Subskriptionen nicht ausgeben\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr "" +" --no-synchronized-snapshots keine synchronisierten Snapshots in parallelen\n" +" Jobs verwenden\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces Tablespace-Zuordnungen nicht ausgeben\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression TOAST-Komprimierungsmethoden nicht ausgeben\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data Daten in ungeloggten Tabellen nicht ausgeben\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing INSERT-Befehle mit ON CONFLICT DO NOTHING ausgeben\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers alle Bezeichner in Anführungszeichen, selbst wenn\n" +" kein Schlüsselwort\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=ANZAHL Anzahl Zeilen pro INSERT; impliziert --inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=ABSCHNITT angegebenen Abschnitt ausgeben (pre-data, data\n" +" oder post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable warten bis der Dump ohne Anomalien laufen kann\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT angegebenen Snapshot für den Dump verwenden\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names Tabellen- oder Schemamuster müssen auf mindestens\n" +" je ein Objekt passen\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" SET SESSION AUTHORIZATION Befehle statt ALTER\n" +" OWNER Befehle verwenden, um Eigentümerschaft zu\n" +" setzen\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Verbindungsoptionen:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME auszugebende Datenbank\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT Portnummer des Datenbankservers\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NAME Datenbankbenutzername\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password niemals nach Passwort fragen\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password nach Passwort fragen (sollte automatisch geschehen)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLLENNAME vor der Ausgabe SET ROLE ausführen\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Wenn kein Datenbankname angegeben wird, dann wird die Umgebungsvariable\n" +"PGDATABASE verwendet.\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Berichten Sie Fehler an <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s Homepage: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "ungültige Clientkodierung »%s« angegeben" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synchronisierte Snapshots auf Standby-Servern werden von dieser Serverversion nicht unterstützt.\n" +"Verwenden Sie --no-synchronized-snapshots, wenn Sie keine synchronisierten\n" +"Snapshots benötigen." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "ungültiges Ausgabeformat »%s« angegeben" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "falscher qualifizierter Name (zu viele Namensteile): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "keine passenden Schemas für Muster »%s« gefunden" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "keine passenden Erweiterungen für Muster »%s« gefunden" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "keine passenden Fremdserver für Muster »%s« gefunden" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "falscher Relationsname (zu viele Namensteile): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "keine passenden Tabellen für Muster »%s« gefunden" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "Sie sind gegenwärtig nicht mit einer Datenbank verbunden." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "Verweise auf andere Datenbanken sind nicht implementiert: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "gebe Inhalt der Tabelle »%s.%s« aus" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Ausgabe des Inhalts der Tabelle »%s« fehlgeschlagen: PQgetCopyData() fehlgeschlagen." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Fehlermeldung vom Server: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "Die Anweisung war: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Ausgabe des Inhalts der Tabelle »%s« fehlgeschlagen: PQgetResult() fehlgeschlagen." + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "falsche Anzahl Felder von Tabelle »%s« erhalten" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "sichere Datenbankdefinition" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "sichere Kodierung = %s" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "sichere standard_conforming_strings = %s" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "konnte Ergebnis von current_schemas() nicht interpretieren" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "sichere search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "lese Large Objects" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "sichere Large Objects" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "Fehler beim Lesen von Large Object %u: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "lese Policys für Sicherheit auf Zeilenebene" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "unerwarteter Policy-Befehlstyp: %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "Eigentümer der Publikation »%s« scheint ungültig zu sein" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "Subskriptionen werden nicht ausgegeben, weil der aktuelle Benutzer kein Superuser ist" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "Eigentümer der Subskription »%s« scheint ungültig zu sein" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "konnte subpublications-Array nicht interpretieren" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "konnte Erweiterung, zu der %s %s gehört, nicht finden" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "Eigentümer des Schemas »%s« scheint ungültig zu sein" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "Schema mit OID %u existiert nicht" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "Eigentümer des Datentypen »%s« scheint ungültig zu sein" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "Eigentümer des Operatoren »%s« scheint ungültig zu sein" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "Eigentümer der Operatorklasse »%s« scheint ungültig zu sein" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "Eigentümer der Operatorfamilie »%s« scheint ungültig zu sein" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "Eigentümer der Aggregatfunktion »%s« scheint ungültig zu sein" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "Eigentümer der Funktion »%s« scheint ungültig zu sein" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "Eigentümer der Tabelle »%s« scheint ungültig zu sein" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "Sanity-Check fehlgeschlagen, Elterntabelle mit OID %u von Sequenz mit OID %u nicht gefunden" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "lese Indexe von Tabelle »%s.%s«" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "lese Fremdschlüssel-Constraints von Tabelle »%s.%s«" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "Sanity-Check fehlgeschlagen, Elterntabelle mit OID %u von pg_rewrite-Eintrag mit OID %u nicht gefunden" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "lese Trigger von Tabelle »%s.%s«" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "Anfrage ergab NULL als Name der Tabelle auf die sich Fremdschlüssel-Trigger »%s« von Tabelle »%s« bezieht (OID der Tabelle: %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "finde Spalten und Typen von Tabelle »%s.%s«" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "ungültige Spaltennummerierung in Tabelle »%s«" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "finde DEFAULT-Ausdrücke von Tabelle »%s.%s«" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "ungültiger adnum-Wert %d für Tabelle »%s«" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "finde Check-Constraints für Tabelle »%s.%s«" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "%d Check-Constraint für Tabelle %s erwartet, aber %d gefunden" +msgstr[1] "%d Check-Constraints für Tabelle %s erwartet, aber %d gefunden" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Die Systemkataloge sind wahrscheinlich verfälscht.)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "typtype des Datentypen »%s« scheint ungültig zu sein" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "unsinniger Wert in proargmodes-Array" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "konnte proallargtypes-Array nicht interpretieren" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "konnte proargmodes-Array nicht interpretieren" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "konnte proargnames-Array nicht interpretieren" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "konnte proconfig-Array nicht interpretieren" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "ungültiger provolatile-Wert für Funktion »%s«" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "ungültiger proparallel-Wert für Funktion »%s«" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "konnte Funktionsdefinition für Funktion mit OID %u nicht finden" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "unsinniger Wert in Feld pg_cast.castfunc oder pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "unsinniger Wert in Feld pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "unsinnige Transformationsdefinition, mindestens eins von trffromsql und trftosql sollte nicht null sein" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "unsinniger Wert in Feld pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "unsinniger Wert in Feld pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "Postfix-Operatoren werden nicht mehr unterstützt (Operator »%s«)" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "konnte Operator mit OID %s nicht finden" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "ungültiger Typ »%c« für Zugriffsmethode »%s«" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "unbekannter Sortierfolgen-Provider: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "unbekannter aggfinalmodify-Wert für Aggregat »%s«" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "unbekannter aggmfinalmodify-Wert für Aggregat »%s«" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "unbekannter Objekttyp in den Vorgabeprivilegien: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "konnte Vorgabe-ACL-Liste (%s) nicht interpretieren" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "konnte initiale GRANT-ACL-Liste (%s) oder initiale REVOKE-ACL-Liste (%s) für Objekt »%s« (%s) nicht interpretieren" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "konnte GRANT-ACL-Liste (%s) oder REVOKE-ACL-Liste (%s) für Objekt »%s« (%s) nicht interpretieren" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "Anfrage um die Definition der Sicht »%s« zu ermitteln lieferte keine Daten" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "Anfrage um die Definition der Sicht »%s« zu ermitteln lieferte mehr als eine Definition" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "Definition der Sicht »%s« scheint leer zu sein (Länge null)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS wird nicht mehr unterstützt (Tabelle »%s«)" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "ungültige Spaltennummer %d in Tabelle »%s«" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "konnte Indexstatistikspalten nicht interpretieren" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "konnte Indexstatistikwerte nicht interpretieren" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "Anzahl Spalten und Werte für Indexstatistiken stimmt nicht überein" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "fehlender Index für Constraint »%s«" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "unbekannter Constraint-Typ: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "Anfrage nach Daten der Sequenz %s ergab %d Zeile (erwartete 1)" +msgstr[1] "Anfrage nach Daten der Sequenz %s ergab %d Zeilen (erwartete 1)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "unbekannter Sequenztyp: %s" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "unerwarteter tgtype-Wert: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "fehlerhafte Argumentzeichenkette (%s) für Trigger »%s« von Tabelle »%s«" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "Anfrage nach Regel »%s« der Tabelle »%s« fehlgeschlagen: falsche Anzahl Zeilen zurückgegeben" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "konnte referenzierte Erweiterung %u nicht finden" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "konnte Erweiterungskonfigurations-Array nicht interpretieren" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "konnte Erweiterungsbedingungs-Array nicht interpretieren" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "Anzahl Konfigurationen und Bedingungen für Erweiterung stimmt nicht überein" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "lese Abhängigkeitsdaten" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "kein referenzierendes Objekt %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "kein referenziertes Objekt %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "konnte reloptions-Array nicht interpretieren" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "ungültige dumpId %d" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "ungültige Abhängigkeit %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "konnte Abhängigkeitsschleife nicht bestimmen" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "Es gibt zirkuläre Fremdschlüssel-Constraints für diese Tabelle:" +msgstr[1] "Es gibt zirkuläre Fremdschlüssel-Constraints zwischen diesen Tabellen:" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Möglicherweise kann der Dump nur wiederhergestellt werden, wenn --disable-triggers verwendet wird oder die Constraints vorübergehend entfernt werden." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Führen Sie einen vollen Dump statt eines Dumps mit --data-only durch, um dieses Problem zu vermeiden." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "konnte Abhängigkeitsschleife zwischen diesen Elementen nicht auflösen:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Das Programm »%s« wird von %s benötigt, aber wurde nicht im\n" +"selben Verzeichnis wie »%s« gefunden.\n" +"Prüfen Sie Ihre Installation." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Das Programm »%s« wurde von %s gefunden,\n" +"aber es hatte nicht die gleiche Version wie %s.\n" +"Prüfen Sie Ihre Installation." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "Option --exclude-database kann nicht zusammen mit -g/--globals-only, -r/--roles-only oder -t/--tablesspaces-only verwendet werden" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "Optionen -g/--globals-only und -r/--roles-only können nicht zusammen verwendet werden" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "Optionen -g/--globals-only und -t/--tablespaces-only können nicht zusammen verwendet werden" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "Optionen -r/--roles-only und -t/--tablespaces-only können nicht zusammen verwendet werden" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "konnte nicht mit der Datenbank »%s« verbinden" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"konnte nicht mit Datenbank »postgres« oder »template1« verbinden\n" +"Bitte geben Sie eine alternative Datenbank an." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s gibt einen PostgreSQL-Datenbankcluster in eine SQL-Skriptdatei aus.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [OPTION]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=DATEINAME Name der Ausgabedatei\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean Datenbanken vor der Wiedererstellung löschen\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only nur globale Objekte ausgeben, keine Datenbanken\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr "" +" -O, --no-owner Wiederherstellung der Objekteigentümerschaft\n" +" auslassen\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only nur Rollen ausgeben, keine Datenbanken oder\n" +" Tablespaces\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME Superusername für den Dump\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only nur Tablespaces ausgeben, keine Datenbanken oder\n" +" Rollen\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr "" +" --exclude-database=MUSTER Datenbanken deren Name mit MUSTER übereinstimmt\n" +" überspringen\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords Rollenpasswörter nicht mit ausgeben\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=VERBDG mit angegebenen Verbindungsparametern verbinden\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME alternative Standarddatenbank\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Wenn -f/--file nicht verwendet wird, dann wird das SQL-Skript auf die\n" +"Standardausgabe geschrieben.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "mit »pg_« anfangender Rollenname übersprungen (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "konnte ACL-Zeichenkette (%s) für Tablespace »%s« nicht interpretieren" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "Datenbank »%s« übersprungen" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "Ausgabe der Datenbank »%s«" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump für Datenbank »%s« fehlgeschlagen; beende" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "konnte die Ausgabedatei »%s« nicht neu öffnen: %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "führe »%s« aus" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "konnte Version des Servers nicht ermitteln" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "konnte Versionszeichenkette »%s« nicht entziffern" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "führe %s aus" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "entweder -d/--dbname oder -f/--file muss angegeben werden" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "Optionen -d/--dbname und -f/--file können nicht zusammen verwendet werden" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "Optionen -C/--create und -1/--single-transaction können nicht zusammen verwendet werden" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "maximale Anzahl paralleler Jobs ist %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "--single-transaction und mehrere Jobs können nicht zusammen verwendet werden" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "unbekanntes Archivformat »%s«; bitte »c«, »d« oder »t« angeben" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "bei Wiederherstellung ignorierte Fehler: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s stellt eine PostgreSQL-Datenbank wieder her, die mit pg_dump\n" +"gesichert wurde.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [OPTION]... [DATEI]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME mit angegebener Datenbank verbinden\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=DATEINAME Name der Ausgabedatei (- für stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t Format der Backup-Datei (sollte automatisch gehen)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list Inhaltsverzeichnis für dieses Archiv anzeigen\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose »Verbose«-Modus\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Optionen die die Wiederherstellung kontrollieren:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only nur Daten, nicht das Schema, wiederherstellen\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create Zieldatenbank erzeugen\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error bei Fehler beenden, Voreinstellung ist fortsetzen\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME benannten Index wiederherstellen\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr "" +" -j, --jobs=NUM so viele parallele Jobs zur Wiederherstellung\n" +" verwenden\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=DATEINAME Inhaltsverzeichnis aus dieser Datei zur Auswahl oder\n" +" Sortierung der Ausgabe verwenden\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME nur Objekte in diesem Schema wiederherstellen\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, ---exclude-schema=NAME Objekte in diesem Schema nicht wiederherstellen\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) benannte Funktion wiederherstellen\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only nur das Schema, nicht die Daten, wiederherstellen\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAME Name des Superusers, um Trigger auszuschalten\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr "" +" -t, --table=NAME benannte Relation (Tabelle, Sicht, usw.)\n" +" wiederherstellen\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAME benannten Trigger wiederherstellen\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges Wiederherstellung der Zugriffsprivilegien auslassen\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction Wiederherstellung als eine einzige Transaktion\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security Sicherheit auf Zeilenebene einschalten\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments Kommentare nicht wiederherstellen\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables Daten für Tabellen, die nicht erzeugt werden\n" +" konnten, nicht wiederherstellen\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications Publikationen nicht wiederherstellen\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels Security-Labels nicht wiederherstellen\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions Subskriptionen nicht wiederherstellen\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces Tablespace-Zuordnungen nicht wiederherstellen\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=ABSCHNITT angegebenen Abschnitt wiederherstellen (pre-data,\n" +" data oder post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLLENNAME vor der Wiederherstellung SET ROLE ausführen\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Die Optionen -I, -n, -N, -P, -t, -T und --section können kombiniert und mehrfach\n" +"angegeben werden, um mehrere Objekte auszuwählen.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Wenn keine Eingabedatei angegeben ist, wird die Standardeingabe verwendet.\n" +"\n" diff --git a/src/bin/pg_dump/po/el.po b/src/bin/pg_dump/po/el.po new file mode 100644 index 0000000..15b5e09 --- /dev/null +++ b/src/bin/pg_dump/po/el.po @@ -0,0 +1,2713 @@ +# Greek message translation file for pg_dump +# Copyright (C) 2021 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_dump (PostgreSQL) package. +# Georgios Kokolatos , 2021 +# +# +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL) 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2021-11-08 10:17+0000\n" +"PO-Revision-Date: 2021-11-08 11:55+0100\n" +"Last-Translator: Georgios Kokolatos \n" +"Language-Team: \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.0\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "κρίσιμο: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "σφάλμα: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "προειδοποίηση: " + +#: ../../common/exec.c:136 ../../common/exec.c:253 ../../common/exec.c:299 +#, c-format +msgid "could not identify current directory: %m" +msgstr "δεν ήταν δυνατή η αναγνώριση του τρέχοντος καταλόγου: %m" + +#: ../../common/exec.c:155 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "μη έγκυρο δυαδικό αρχείο «%s»" + +#: ../../common/exec.c:205 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "δεν ήταν δυνατή η ανάγνωση του δυαδικού αρχείου «%s»" + +#: ../../common/exec.c:213 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "δεν βρέθηκε το αρχείο «%s» για να εκτελεστεί" + +#: ../../common/exec.c:269 ../../common/exec.c:308 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "δεν ήταν δυνατή η μετάβαση στον κατάλογο «%s»: %m" + +#: ../../common/exec.c:286 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "δεν ήταν δυνατή η ανάγνωση του συμβολικού συνδέσμου «%s»: %m" + +#: ../../common/exec.c:409 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() απέτυχε: %m" + +#: ../../common/exec.c:522 ../../common/exec.c:567 ../../common/exec.c:659 +msgid "out of memory" +msgstr "έλλειψη μνήμης" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "έλλειψη μνήμης\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "δεν ήταν δυνατή η αντιγραφή δείκτη null (εσωτερικό σφάλμα)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "εντολή μη εκτελέσιμη" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "εντολή δεν βρέθηκε" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "απόγονος διεργασίας τερμάτισε με κωδικό εξόδου %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "απόγονος διεργασίας τερματίστηκε με εξαίρεση 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "απόγονος διεργασίας τερματίστηκε με σήμα %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "απόγονος διεργασίας τερμάτισε με μη αναγνωρίσιμη κατάσταση %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "ανάγνωση επεκτάσεων" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "προσδιορισμός μελών επέκτασεων" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "ανάγνωση σχημάτων" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "ανάγνωση πινάκων ορισμένων από το χρήστη" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "ανάγνωση συναρτήσεων ορισμένων από το χρήστη" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "ανάγνωση τύπων ορισμένων από το χρήστη" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "ανάγνωση δομημένων γλωσσών" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "ανάγνωση συναρτήσεων συγκεντρωτικών αποτελεσμάτων ορισμένων από το χρήστη" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "ανάγνωση χειριστών ορισμένων από το χρήστη" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "ανάγνωση μεθόδων πρόσβασης ορισμένων από το χρήστη" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "ανάγνωση κλάσεων χειριστών ορισμένων από το χρήστη" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "ανάγνωση οικογενειών χειριστών ορισμένων από το χρήστη" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "ανάγνωση αναλυτών αναζήτησης κειμένου ορισμένων από το χρήστη" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "ανάγνωση προτύπων αναζήτησης κειμένου ορισμένων από το χρήστη" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "ανάγνωση λεξικών αναζήτησης κειμένου ορισμένων από το χρήστη" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "ανάγνωση ρυθμίσεων παραμέτρων αναζήτησης κειμένου ορισμένων από το χρήστη" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "ανάγνωση περιτυλίξεων ξενικών δεδομένων ορισμένων από το χρήστη" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "ανάγνωση ξενικών διακομιστών ορισμένων από το χρήστη" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "ανάγνωση προεπιλεγμένων δικαιωμάτων" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "ανάγνωση συρραφών ορισμένων από το χρήστη" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "ανάγνωση μετατροπών ορισμένων από το χρήστη" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "ανάγνωση τύπων καστ" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "ανάγωση μετατροπών" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "ανάγωση πληροφοριών κληρονομιάς πινάκων" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "ανάγνωση ενεργοποιήσεων συμβάντων" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "εύρεση πινάκων επέκτασης" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "εύρεση σχέσεων κληρονιμιά" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "ανάγνωση πληροφοριών στήλης για ενδιαφέροντες πίνακες" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "επισήμανση κληρονομούμενων στηλών σε υποπίνακες" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "ανάγνωση ευρετηρίων" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "επισήμανση ευρετηρίων σε κατατμημένους πινάκες" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "ανάγνωση εκτεταμένων στατιστικών στοιχείων" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "ανάγνωση περιορισμών" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "ανάγνωση ενεργοποιήσεων συμβάντων" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "ανάγνωση κανόνων επανεγγραφής" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "ανάγνωση πολιτικών" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "ανάγνωση δημοσιεύσεων" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "ανάγνωση ιδιοτήτων μελών δημοσίευσεων" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "ανάγνωση συνδρομών" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "μη έγκυρος αριθμός γονέων %d για τον πίνακα «%s»" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "απέτυχε ο έλεγχος ακεραιότητας, το γονικό OID %u του πίνακα «%s» (OID %u) δεν βρέθηκε" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "δεν ήταν δυνατή η ανάλυση της αριθμητικής συστοιχίας «%s»: πάρα πολλοί αριθμοί" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "δεν ήταν δυνατή η ανάλυση της αριθμητικής συστοιχίας «%s»: μη έγκυρος χαρακτήρας σε αριθμό" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "μη έγκυρος κωδικός συμπίεσης: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "δεν έχει κατασκευαστεί με υποστήριξη zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "δεν ήταν δυνατή η αρχικοποίηση της βιβλιοθήκης συμπίεσης: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "δεν ήταν δυνατό το κλείσιμο της ροής συμπίεσης: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "δεν ήταν δυνατή η συμπίεση δεδομένων: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "δεν ήταν δυνατή η αποσυμπίεση δεδομένων: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "δεν ήταν δυνατό το κλείσιμο της βιβλιοθήκης συμπίεσης: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:551 pg_backup_tar.c:554 +#, c-format +msgid "could not read from input file: %s" +msgstr "δεν ήταν δυνατή η ανάγνωση από το αρχείο εισόδου: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:552 +#: pg_backup_tar.c:787 pg_backup_tar.c:810 +#, c-format +msgid "could not read from input file: end of file" +msgstr "δεν ήταν δυνατή η ανάγνωση από το αρχείο εισόδου: τέλος αρχείου" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s() απέτυχε: κωδικός σφάλματος %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "δεν ήταν δυνατή η δημιουργία καναλιών επικοινωνίας: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "δεν ήταν δυνατή η δημιουργία διεργασίας εργάτη: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "μη αναγνωρίσιμη εντολή που ελήφθη από τον αρχηγό: «%s»" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "άκυρο μήνυμα που ελήφθη από εργάτη: «%s»" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"δεν ήταν δυνατή η απόκτηση κλειδιού για τη σχέση \"%s\"\n" +"Αυτό συνήθως σημαίνει ότι κάποιος ζήτησε ένα κλειδί ACCESS EXCLUSIVE στον πίνακα αφού η γονική διεργασία pg_dump είχε ήδη αποκτήσει το αρχικό κλειδί ACCESS SHARE στον πίνακα." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "μία διεργασία εργάτη τερματίστηκε απρόσμενα" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "δεν ήταν δυνατή η εγγραφή στο κανάλι επικοινωνίας: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η δημιουργία υποδοχέα: κωδικός σφάλματος %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η δέσμευση: κωδικός σφάλματος %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η ακρόαση: κωδικός σφάλματος %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "%s() απέτυχε: κωδικός σφάλματος %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η δημιουργία δεύτερης υποδοχής: κωδικός σφάλματος %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η σύνδεση της υποδοχής: κωδικός σφάλματος %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: δεν ήταν δυνατή η αποδοχή σύνδεσης: κωδικός σφάλματος %d" + +#: pg_backup_archiver.c:277 pg_backup_archiver.c:1576 +#, c-format +msgid "could not close output file: %m" +msgstr "δεν ήταν δυνατό το κλείσιμο αρχείου εξόδου: %m" + +#: pg_backup_archiver.c:321 pg_backup_archiver.c:325 +#, c-format +msgid "archive items not in correct section order" +msgstr "αρχειοθέτηση στοιχείων που δεν βρίσκονται σε σωστή σειρά ενότητας" + +#: pg_backup_archiver.c:331 +#, c-format +msgid "unexpected section code %d" +msgstr "μη αναμενόμενος κώδικας ενότητας %d" + +#: pg_backup_archiver.c:368 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "η παράλληλη επαναφορά δεν υποστηρίζεται από αυτήν τη μορφή αρχείου αρχειοθέτησης" + +#: pg_backup_archiver.c:372 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "η παράλληλη επαναφορά δεν υποστηρίζεται με αρχεία που έγιναν από pg_dump προ έκδοσης 8.0" + +#: pg_backup_archiver.c:390 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "δεν είναι δυνατή η επαναφορά από συμπιεσμένη αρχειοθήκη (η συμπίεση δεν υποστηρίζεται σε αυτήν την εγκατάσταση)" + +#: pg_backup_archiver.c:407 +#, c-format +msgid "connecting to database for restore" +msgstr "σύνδεση με βάση δεδομένων για επαναφορά" + +#: pg_backup_archiver.c:409 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "οι απευθείας συνδέσεις βάσεων δεδομένων δεν υποστηρίζονται σε προ-1.3 αρχεία" + +#: pg_backup_archiver.c:452 +#, c-format +msgid "implied data-only restore" +msgstr "υποδηλούμενη επαναφορά μόνο δεδομένων" + +#: pg_backup_archiver.c:518 +#, c-format +msgid "dropping %s %s" +msgstr "εγκαταλείπει %s: %s" + +#: pg_backup_archiver.c:613 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "δεν ήταν δυνατή η εύρεση του σημείου εισαγωγής IF EXISTS στη δήλωση «%s»" + +#: pg_backup_archiver.c:769 pg_backup_archiver.c:771 +#, c-format +msgid "warning from original dump file: %s" +msgstr "προειδοποίηση από το αρχικό αρχείο απόθεσης: %s" + +#: pg_backup_archiver.c:786 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "δημιουργία %s «%s.%s»" + +#: pg_backup_archiver.c:789 +#, c-format +msgid "creating %s \"%s\"" +msgstr "δημιουργία %s «%s»" + +#: pg_backup_archiver.c:839 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "σύνδεση με νέα βάση δεδομένων «%s»" + +#: pg_backup_archiver.c:866 +#, c-format +msgid "processing %s" +msgstr "επεξεργασία %s" + +#: pg_backup_archiver.c:886 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "επεξεργασία δεδομένων για τον πίνακα «%s.%s»" + +#: pg_backup_archiver.c:948 +#, c-format +msgid "executing %s %s" +msgstr "εκτέλεση %s %s" + +#: pg_backup_archiver.c:987 +#, c-format +msgid "disabling triggers for %s" +msgstr "απενεργοποίηση ενεργοποιήσεων για %s" + +#: pg_backup_archiver.c:1013 +#, c-format +msgid "enabling triggers for %s" +msgstr "ενεργοποίηση ενεργοποιήσεων για %s" + +#: pg_backup_archiver.c:1041 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "εσωτερικό σφάλμα -- Δεν είναι δυνατή η κλήση του WriteData εκτός του περιβάλλοντος μιας ρουτίνας DataDumper" + +#: pg_backup_archiver.c:1224 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "η έξοδος μεγάλου αντικειμένου δεν υποστηρίζεται στην επιλεγμένη μορφή" + +#: pg_backup_archiver.c:1282 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "επανέφερε %d μεγάλο αντικείμενο" +msgstr[1] "επανέφερε %d μεγάλα αντικείμενα" + +#: pg_backup_archiver.c:1303 pg_backup_tar.c:730 +#, c-format +msgid "restoring large object with OID %u" +msgstr "επαναφορά μεγάλου αντικειμένου με OID %u" + +#: pg_backup_archiver.c:1315 +#, c-format +msgid "could not create large object %u: %s" +msgstr "δεν ήταν δυνατή η δημιουργία μεγάλου αντικειμένου %u: %s" + +#: pg_backup_archiver.c:1320 pg_dump.c:3638 +#, c-format +msgid "could not open large object %u: %s" +msgstr "δεν ήταν δυνατό το άνοιγμα μεγάλου αντικειμένου %u: %s" + +#: pg_backup_archiver.c:1376 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC «%s»: %m" + +#: pg_backup_archiver.c:1404 +#, c-format +msgid "line ignored: %s" +msgstr "παραβλέπεται γραμμή: %s" + +#: pg_backup_archiver.c:1411 +#, c-format +msgid "could not find entry for ID %d" +msgstr "δεν ήταν δυνατή η εύρεση καταχώρησης για ID %d" + +#: pg_backup_archiver.c:1434 pg_backup_directory.c:222 +#: pg_backup_directory.c:598 +#, c-format +msgid "could not close TOC file: %m" +msgstr "δεν ήταν δυνατό το κλείσιμο του αρχείου TOC %m" + +#: pg_backup_archiver.c:1548 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:585 pg_backup_directory.c:648 +#: pg_backup_directory.c:667 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "δεν ήταν δυνατό το άνοιγμα του αρχείου εξόδου «%s»: %m" + +#: pg_backup_archiver.c:1550 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου εξόδου %m" + +#: pg_backup_archiver.c:1643 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "έγραψε %zu byte δεδομένων μεγάλου αντικειμένου (αποτέλεσμα = %d)" +msgstr[1] "έγραψε %zu bytes δεδομένων μεγάλου αντικειμένου (αποτέλεσμα = %d)" + +#: pg_backup_archiver.c:1649 +#, c-format +msgid "could not write to large object: %s" +msgstr "δεν ήταν δυνατή η εγγραφή σε μεγάλο αντικείμενο: %s" + +#: pg_backup_archiver.c:1739 +#, c-format +msgid "while INITIALIZING:" +msgstr "ενόσω INITIALIZING:" + +#: pg_backup_archiver.c:1744 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "ενόσω PROCESSING TOC:" + +#: pg_backup_archiver.c:1749 +#, c-format +msgid "while FINALIZING:" +msgstr "ενόσω FINALIZING:" + +#: pg_backup_archiver.c:1754 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "από καταχώρηση TOC %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1830 +#, c-format +msgid "bad dumpId" +msgstr "εσφαλμένο dumpId" + +#: pg_backup_archiver.c:1851 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "εσφαλμένος πίνακας dumpId για στοιχείο TABLE DATA" + +#: pg_backup_archiver.c:1943 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "μη αναμενόμενη σημαία όφσετ δεδομένων %d" + +#: pg_backup_archiver.c:1956 +#, c-format +msgid "file offset in dump file is too large" +msgstr "το όφσετ αρχείου στο αρχείο απόθεσης είναι πολύ μεγάλο" + +#: pg_backup_archiver.c:2094 pg_backup_archiver.c:2104 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "πολύ μακρύ όνομα καταλόγου: «%s»" + +#: pg_backup_archiver.c:2112 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "ο κατάλογος «%s» δεν φαίνεται να είναι έγκυρη αρχειοθήκη (το «toc.dat» δεν υπάρχει)" + +#: pg_backup_archiver.c:2120 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:394 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "δεν ήταν δυνατό το άνοιγμα του αρχείου εισόδου «%s»: %m" + +#: pg_backup_archiver.c:2127 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου εισόδου %m" + +#: pg_backup_archiver.c:2133 +#, c-format +msgid "could not read input file: %m" +msgstr "δεν ήταν δυνατή η ανάγνωση αρχείου εισόδου: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "το αρχείο εισόδου είναι πολύ σύντομο (διάβασε %lu, ανάμενε 5)" + +#: pg_backup_archiver.c:2167 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "το αρχείο εισαγωγής φαίνεται να είναι απόθεση μορφής κειμένου. Παρακαλώ χρησιμοποιήστε το psql." + +#: pg_backup_archiver.c:2173 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "το αρχείο εισόδου δεν φαίνεται να είναι έγκυρη αρχειοθήκη (πολύ σύντομο;)" + +#: pg_backup_archiver.c:2179 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "το αρχείο εισόδου δεν φαίνεται να είναι έγκυρη αρχειοθήκη" + +#: pg_backup_archiver.c:2188 +#, c-format +msgid "could not close input file: %m" +msgstr "δεν ήταν δυνατό το κλείσιμο αρχείου εισόδου: %m" + +#: pg_backup_archiver.c:2305 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "μη αναγνωρίσιμη μορφή αρχείου «%d»" + +#: pg_backup_archiver.c:2387 pg_backup_archiver.c:4411 +#, c-format +msgid "finished item %d %s %s" +msgstr "τερματισμός στοιχείου %d %s %s" + +#: pg_backup_archiver.c:2391 pg_backup_archiver.c:4424 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "διεργασία εργάτη απέτυχε: κωδικός εξόδου %d" + +#: pg_backup_archiver.c:2511 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "καταχώρηση με ID %d εκτός εύρους τιμών -- ίσως αλλοιωμένο TOC" + +#: pg_backup_archiver.c:2578 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "η επαναφορά πινάκων WITH OIDS δεν υποστηρίζεται πλέον" + +#: pg_backup_archiver.c:2660 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "μη αναγνωρίσιμη κωδικοποίηση «%s»" + +#: pg_backup_archiver.c:2665 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "μη έγκυρο στοιχείο ENCODING: %s" + +#: pg_backup_archiver.c:2683 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "μη έγκυρο στοιχείο STDSTRINGS: %s" + +#: pg_backup_archiver.c:2708 +#, c-format +msgid "schema \"%s\" not found" +msgstr "το σχήμα «%s» δεν βρέθηκε" + +#: pg_backup_archiver.c:2715 +#, c-format +msgid "table \"%s\" not found" +msgstr "ο πίνακας «%s» δεν βρέθηκε" + +#: pg_backup_archiver.c:2722 +#, c-format +msgid "index \"%s\" not found" +msgstr "το ευρετήριο «%s» δεν βρέθηκε" + +#: pg_backup_archiver.c:2729 +#, c-format +msgid "function \"%s\" not found" +msgstr "η συνάρτηση «%s» δεν βρέθηκε" + +#: pg_backup_archiver.c:2736 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "η ενεργοποίηση «%s» δεν βρέθηκε" + +#: pg_backup_archiver.c:3128 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "δεν ήταν δυνατός ο ορισμός του χρήστη συνεδρίας σε «%s»: %s" + +#: pg_backup_archiver.c:3260 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "δεν ήταν δυνατός ο ορισμός του search_path σε «%s»: %s" + +#: pg_backup_archiver.c:3322 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "δεν ήταν δυνατός ο ορισμός του default_tablespace σε «%s»: %s" + +#: pg_backup_archiver.c:3367 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "δεν ήταν δυνατός ο ορισμός του default_table_access_method: %s" + +#: pg_backup_archiver.c:3459 pg_backup_archiver.c:3617 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "δεν γνωρίζω πώς να οριστεί κάτοχος για τύπο αντικειμένου «%s»" + +#: pg_backup_archiver.c:3720 +#, c-format +msgid "did not find magic string in file header" +msgstr "δεν βρέθηκε μαγική συμβολοσειρά στην κεφαλίδα αρχείου" + +#: pg_backup_archiver.c:3734 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "μη υποστηριζόμενη έκδοση (%d.%d) στην κεφαλίδα αρχείου" + +#: pg_backup_archiver.c:3739 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "απέτυχε έλεγχος ακεραιότητας για μέγεθος ακεραίου (%lu)" + +#: pg_backup_archiver.c:3743 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "το αρχείο δημιουργήθηκε σε έναν υπολογιστή με μεγαλύτερους ακέραιους, ορισμένες λειτουργίες ενδέχεται να αποτύχουν" + +#: pg_backup_archiver.c:3753 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "η αναμενόμενη μορφή (%d) διαφέρει από τη μορφή που βρίσκεται στο αρχείο (%d)" + +#: pg_backup_archiver.c:3768 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "το αρχείο είναι συμπιεσμένο, αλλά αυτή η εγκατάσταση δεν υποστηρίζει συμπίεση -- δεν θα υπάρχουν διαθέσιμα δεδομένα" + +#: pg_backup_archiver.c:3802 +#, c-format +msgid "invalid creation date in header" +msgstr "μη έγκυρη ημερομηνία δημιουργίας στην κεφαλίδα" + +#: pg_backup_archiver.c:3936 +#, c-format +msgid "processing item %d %s %s" +msgstr "επεξεργασία στοιχείου %d %s %s" + +#: pg_backup_archiver.c:4015 +#, c-format +msgid "entering main parallel loop" +msgstr "εισέρχεται στο κύριο παράλληλο βρόχο" + +#: pg_backup_archiver.c:4026 +#, c-format +msgid "skipping item %d %s %s" +msgstr "παράβλεψη στοιχείου %d %s %s" + +#: pg_backup_archiver.c:4035 +#, c-format +msgid "launching item %d %s %s" +msgstr "εκκίνηση στοιχείου %d %s %s" + +#: pg_backup_archiver.c:4089 +#, c-format +msgid "finished main parallel loop" +msgstr "εξέρχεται από το κύριο παράλληλο βρόχο" + +#: pg_backup_archiver.c:4125 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "επεξεργασία παραβλεπόμενου στοιχείου %d %s %s" + +#: pg_backup_archiver.c:4730 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "δεν ήταν δυνατή η δημιουργία του πίνακα «%s», δεν θα επαναφερθούν τα δεδομένα του" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "μη έγκυρο OID για μεγάλο αντικειμένο" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1080 pg_backup_tar.c:1085 +#, c-format +msgid "error during file seek: %m" +msgstr "σφάλμα κατά τη διάρκεια αναζήτησης σε αρχείο: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "%d μπλοκ δεδομένων έχει εσφαλμένη θέση αναζήτησης" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "τύπος μπλοκ δεδομένων (%d) που δεν αναγνωρίζεται κατά την αναζήτηση αρχειοθέτησης" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "δεν ήταν δυνατή η εύρεση μπλοκ ID %d στο αρχείο -- πιθανώς λόγω αίτησης επαναφοράς εκτός σειράς, η οποία δεν είναι δυνατό να αντιμετωπιστεί λόγω μη αναζητήσιμου αρχείου εισόδου" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "δεν ήταν δυνατή η εύρεση μπλοκ ID %d στην αρχειοθήκη -- πιθανώς αλλοιωμένη αρχειοθήκη" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "βρέθηκε μη αναμενόμενο μπλοκ ID (%d) κατά την ανάγνωση δεδομένων -- αναμενόμενο %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "μη αναγνωρίσιμος τύπος μπλοκ δεδομένων %d κατά την επαναφορά της αρχειοθήκης" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "δεν ήταν δυνατή η ανάγνωση από αρχείο: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1083 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "δεν ήταν δυνατός ο προσδιορισμός της θέσης αναζήτησης στην αρχειοθήκη: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "δεν ήταν δυνατό το κλείσιμο της αρχειοθήκης: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "μπορεί να επα-ανοίξει μόνο αρχειοθήκες εισόδου" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "η επαναφορά από τυπική είσοδο δεν υποστηρίζεται" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "η παράλληλη επαναφορά από μη αναζητήσιμο αρχείο δεν υποστηρίζεται" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "δεν ήταν δυνατή η αναζήτηση θέσης στο αρχείο αρχειοθέτησης: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "συμπιεστής ενεργός" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "δεν ήταν δυνατή η απόκτηση server_version από libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1826 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "έκδοση διακομιστή: %s; %s έκδοση: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1828 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "ματαίωση λόγω ασυμφωνίας έκδοσης διακομιστή" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "ήδη συνδεδεμένος σε βάση δεδομένων" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1655 pg_dumpall.c:1766 +msgid "Password: " +msgstr "Κωδικός πρόσβασης: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "δεν ήταν δυνατή η σύνδεση σε βάση δεδομένων" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "επανασύνδεση απέτυχε: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1686 pg_dumpall.c:1776 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1889 pg_dumpall.c:1912 +#, c-format +msgid "query failed: %s" +msgstr "το ερώτημα απέτυχε: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1890 pg_dumpall.c:1913 +#, c-format +msgid "query was: %s" +msgstr "το ερώτημα ήταν: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "το ερώτημα επέστρεψε %d σειρά αντί μίας: %s" +msgstr[1] "το ερώτημα επέστρεψε %d σειρές αντί μίας: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %s η εντολή ήταν: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "δεν ήταν δυνατή η εκτέλεση ερωτήματος" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "επιστράφηκε σφάλμα από PQputCopyData: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "επιστράφηκε σφάλμα από PQputCopyEnd: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY απέτυχε για πίνακα «%s»: %s" + +#: pg_backup_db.c:525 pg_dump.c:2074 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "μη αναμενόμενα αποτελέσματα κατά τη διάρκεια COPY του πίνακα «%s»" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "δεν ήταν δυνατή η εκκίνηση συναλλαγής βάσης δεδομένων" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "δεν ήταν δυνατή η ολοκλήρωση της συναλλαγής βάσης δεδομένων" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "δεν ορίστηκε κατάλογος δεδομένων εξόδου" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "δεν ήταν δυνατή η ανάγνωση του καταλόγου «%s»: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "δεν ήταν δυνατό το κλείσιμο του καταλόγου «%s»: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "δεν ήταν δυνατή η δημιουργία του καταλόγου «%s»: %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:496 +#: pg_backup_directory.c:532 +#, c-format +msgid "could not write to output file: %s" +msgstr "δεν ήταν δυνατή η εγγραφή εξόδου στο αρχείο: %s" + +#: pg_backup_directory.c:406 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "δεν ήταν δυνατό το κλείσιμο του αρχείου δεδομένων «%s»: %m" + +#: pg_backup_directory.c:446 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC μεγάλου αντικειμένου «%s» για είσοδο: %m" + +#: pg_backup_directory.c:457 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "μη έγκυρη γραμμή σε αρχείο TOC μεγάλου αντικειμένου «%s»: «%s»" + +#: pg_backup_directory.c:466 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "σφάλμα κατά την ανάγνωση αρχείου TOC μεγάλου αντικειμένου «%s»" + +#: pg_backup_directory.c:470 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "δεν ήταν δυνατό το κλείσιμο αρχείου TOC μεγάλου αντικειμένου «%s»: %m" + +#: pg_backup_directory.c:689 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "δεν ήταν δυνατή η εγγραφή σε αρχείο TOC blobs" + +#: pg_backup_directory.c:721 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "πολύ μακρύ όνομα αρχείου: «%s»" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "δεν είναι δυνατή η ανάγνωση αυτής της μορφής" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC «%s» για έξοδο: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC για έξοδο: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "δεν υποστηρίζεται συμπίεση από τη μορφή αρχειοθέτησης tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC «%s» για είσοδο: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "δεν ήταν δυνατό το άνοιγμα αρχείου TOC για είσοδο: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "δεν ήταν δυνατή η εύρεση του αρχείου «%s» στην αρχειοθήκη" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "δεν ήταν δυνατή η δημιουργία ονόματος προσωρινού αρχείου: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "δεν ήταν δυνατό το άνοιγμα του προσωρινού αρχείου" + +#: pg_backup_tar.c:442 +#, c-format +msgid "could not close tar member" +msgstr "δεν ήταν δυνατό το κλείσιμο μέλους tar" + +#: pg_backup_tar.c:685 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "μη αναμενόμενη σύνταξη πρότασης COPY: «%s»" + +#: pg_backup_tar.c:952 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "μη έγκυρο OID για μεγάλο αντικείμενο (%u)" + +#: pg_backup_tar.c:1099 +#, c-format +msgid "could not close temporary file: %m" +msgstr "δεν ήταν δυνατό το κλείσιμο προσωρινού αρχείου: %m" + +#: pg_backup_tar.c:1108 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "πραγματικό μήκος αρχείου (%s) δεν συμφωνεί με το αναμενόμενο (%s)" + +#: pg_backup_tar.c:1165 pg_backup_tar.c:1196 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "δεν ήταν δυνατή η εύρεση κεφαλίδας για το αρχείο «%s» στο αρχείο tar" + +#: pg_backup_tar.c:1183 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "η επαναφορά δεδομένων εκτός σειράς δεν υποστηρίζεται σε αυτήν τη μορφή αρχειοθέτησης: απαιτείται «%s», αλλά προηγείται της «%s» στο αρχείο αρχειοθέτησης." + +#: pg_backup_tar.c:1230 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "βρέθηκε ατελής κεφαλίδα tar (%lu byte)" +msgstr[1] "βρέθηκε ατελής κεφαλίδα tar (%lu bytes)" + +#: pg_backup_tar.c:1281 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "αλλοιωμένη κεφαλίδα tar βρέθηκε σε %s (αναμενόμενη %d, υπολογισμένη %d) θέση αρχείου %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "μη αναγνωρισμένο όνομα τμήματος: «%s»" + +#: pg_backup_utils.c:55 pg_dump.c:622 pg_dump.c:639 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Δοκιμάστε «%s --help» για περισσότερες πληροφορίες.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "έλλειψη υποδοχών on_exit_nicely" + +#: pg_dump.c:548 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "το επίπεδο συμπίεσης πρέπει να βρίσκεται στο εύρος 0..9" + +#: pg_dump.c:586 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits πρέπει να βρίσκονται στο εύρος -15..3" + +#: pg_dump.c:609 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert πρέπει να βρίσκονται στο εύρος %d..%d" + +#: pg_dump.c:637 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "πάρα πολλές παράμετροι εισόδου από την γραμμή εντολών (η πρώτη είναι η «%s»)" + +#: pg_dump.c:658 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "οι επιλογές -s/--schema-only και -a/--data-only δεν είναι δυνατό να χρησιμοποιηθούν μαζί" + +#: pg_dump.c:663 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "οι επιλογές -s/--schema-only και --include-foreign-data δεν είναι δυνατό να χρησιμοποιηθούν μαζί" + +#: pg_dump.c:666 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "η επιλογή --include-foreign-data δεν υποστηρίζεται με παράλληλη δημιουργία αντιγράφων ασφαλείας" + +#: pg_dump.c:670 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "οι επιλογές -c/--clean και -a/--data-only δεν είναι δυνατό να χρησιμοποιηθούν μαζί" + +#: pg_dump.c:675 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "η επιλογή --if-exists απαιτεί την επιλογή -c/--clean" + +#: pg_dump.c:682 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "η επιλογή --on-conflict-do-nothing απαιτεί την επιλογή --inserts, --rows-per-insert, ή --column-inserts" + +#: pg_dump.c:704 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "η συμπίεση που ζητήθηκε δεν είναι διαθέσιμη σε αυτήν την εγκατάσταση -- η αρχειοθήκη θα είναι ασυμπίεστη" + +#: pg_dump.c:725 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "μη έγκυρος αριθμός παράλληλων εργασιών" + +#: pg_dump.c:729 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "παράλληλο αντίγραφο ασφαλείας υποστηρίζεται μόνο από μορφή καταλόγου" + +#: pg_dump.c:784 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Τα συγχρονισμένα στιγμιότυπα δεν υποστηρίζονται από αυτήν την έκδοση διακομιστή.\n" +"Εκτελέστε με --no-synchronized-snapshots, εάν δεν χρειάζεστε\n" +"συγχρονισμένα στιγμιότυπα." + +#: pg_dump.c:790 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Τα εξαγόμενα στιγμιότυπα δεν υποστηρίζονται από αυτήν την έκδοση διακομιστή." + +#: pg_dump.c:802 +#, c-format +msgid "last built-in OID is %u" +msgstr "το τελευταίο ενσωματωμένο OID είναι %u" + +#: pg_dump.c:811 +#, c-format +msgid "no matching schemas were found" +msgstr "δεν βρέθηκαν σχήματα που να ταιριάζουν" + +#: pg_dump.c:825 +#, c-format +msgid "no matching tables were found" +msgstr "δεν βρέθηκαν πίνακες που να ταιριάζουν" + +#: pg_dump.c:847 +#, c-format +msgid "no matching extensions were found" +msgstr "δεν βρέθηκαν επεκτάσεις που να ταιριάζουν" + +#: pg_dump.c:1017 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s αποθέτει μια βάση δεδομένων ως αρχείο κειμένου ή σε άλλες μορφές.\n" +"\n" + +#: pg_dump.c:1018 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Χρήση:\n" + +#: pg_dump.c:1019 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [ΕΠΙΛΟΓΗ]... [DBNAME]\n" + +#: pg_dump.c:1021 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Γενικές επιλογές:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=FILENAME αρχείο εξόδου ή όνομα καταλόγου\n" + +#: pg_dump.c:1023 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p μορφή αρχείου εξόδου (προσαρμοσμένη, κατάλογος, tar,\n" +" απλό κείμενο (προεπιλογή))\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM χρησιμοποιήστε τόσες πολλές παράλληλες εργασίες για απόθεση\n" + +#: pg_dump.c:1026 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose περιφραστική λειτουργία\n" + +#: pg_dump.c:1027 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version εμφάνισε πληροφορίες έκδοσης και, στη συνέχεια, έξοδος\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 επίπεδο συμπίεσης για συμπιεσμένες μορφές\n" + +#: pg_dump.c:1029 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT αποτυγχάνει μετά την αναμονή TIMEOUT για το κλείδωμα πίνακα\n" + +#: pg_dump.c:1030 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync να μην αναμένει την ασφαλή εγγραφή αλλαγών στον δίσκο\n" + +#: pg_dump.c:1031 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help εμφάνισε αυτό το μήνυμα βοήθειας, και μετά έξοδος\n" + +#: pg_dump.c:1033 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Επιλογές που ελέγχουν το περιεχόμενο εξόδου:\n" + +#: pg_dump.c:1034 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only αποθέτει μόνο τα δεδομένα, όχι το σχήμα\n" + +#: pg_dump.c:1035 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs περιέλαβε μεγάλα αντικείμενα στην απόθεση\n" + +#: pg_dump.c:1036 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs εξαίρεσε μεγάλα αντικείμενα στην απόθεση\n" + +#: pg_dump.c:1037 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean καθάρισε (εγκατάληψε) αντικείμενα βάσης δεδομένων πριν από την αναδημιουργία\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create συμπεριέλαβε εντολές για τη δημιουργία βάσης δεδομένων στην απόθεση\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=PATTERN απόριψε μόνο τις καθορισμένες επεκτάσεις\n" + +#: pg_dump.c:1040 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=ENCODING απόθεσε τα δεδομένα στην κωδικοποίηση ENCODING\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATTERN απόθεση μόνο για τα καθορισμένα σχήματα\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN να ΜΗΝ αποθέσει τα καθορισμένα σχήματα\n" + +#: pg_dump.c:1043 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner παράλειπε την αποκατάσταση της κυριότητας των αντικειμένων στη\n" +" μορφή απλού κειμένου\n" + +#: pg_dump.c:1045 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only απόθεση μόνο το σχήμα, χωρίς δεδομένα\n" + +#: pg_dump.c:1046 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME όνομα χρήστη υπερ-χρήστη που θα χρησιμοποιηθεί σε μορφή απλού κειμένου\n" + +#: pg_dump.c:1047 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATTERN απόθεση μόνο των καθορισμένων πινάκων\n" + +#: pg_dump.c:1048 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATTERN να ΜΗΝ αποθέτει τους καθορισμένους πίνακες\n" + +#: pg_dump.c:1049 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges να ΜΗΝ αποθέτει δικαιώματα (εκχώρηση/ανάκληση)\n" + +#: pg_dump.c:1050 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade μόνο για χρήση μόνο από βοηθητικά προγράμματα αναβάθμισης\n" + +#: pg_dump.c:1051 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts αποθέτει δεδομένα ως εντολές INSERT με ονόματα στηλών\n" + +#: pg_dump.c:1052 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr " --disable-dollar-quoting απενεργοποίησε την παράθεση δολαρίου, χρήση τυποποιημένης παράθεσης SQL\n" + +#: pg_dump.c:1053 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers απενεργοποίησε τα εναύσματα κατά την επαναφορά δεδομένων-μόνο\n" + +#: pg_dump.c:1054 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security ενεργοποιήστε την ασφάλεια σειρών (απόθεση μόνο του περιεχομένου που ο χρήστης έχει\n" +" πρόσβαση)\n" + +#: pg_dump.c:1056 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATTERN να ΜΗΝ αποθέσει δεδομένα για τους καθορισμένους πίνακες\n" + +#: pg_dump.c:1057 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM παράκαμψε την προεπιλεγμένη ρύθμιση για extra_float_digits\n" + +#: pg_dump.c:1058 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists χρησιμοποίησε το IF EXISTS κατά την εγκαταλήψη αντικειμένων\n" + +#: pg_dump.c:1059 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=PATTERN\n" +" περιέλαβε δεδομένα ξένων πινάκων για\n" +" διακομιστές που ταιριάζουν με PATTERN\n" + +#: pg_dump.c:1062 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts απόθεσε δεδομένα ως εντολές INSERT, αντί για COPY\n" + +#: pg_dump.c:1063 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root φόρτωσε διαχωρίσματα μέσω του βασικού πίνακα\n" + +#: pg_dump.c:1064 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments να μην αποθέσεις σχόλια\n" + +#: pg_dump.c:1065 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications να μην αποθέσεις δημοσιεύσεις\n" + +#: pg_dump.c:1066 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels να μην αποθέσεις αντιστοιχίσεις ετικετών ασφαλείας\n" + +#: pg_dump.c:1067 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-publications να μην αποθέσεις συνδρομές\n" + +#: pg_dump.c:1068 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots να μην χρησιμοποιήσει συγχρονισμένα στιγμιότυπα σε παράλληλες εργασίες\n" + +#: pg_dump.c:1069 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces να μην αποθέσει αναθέσεις πινακοχώρος\n" + +#: pg_dump.c:1070 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression να μην αποθέσει τις μεθόδους συμπίεσης TOAST\n" + +#: pg_dump.c:1071 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data να μην αποθέσει μη δεδομένα μη-καταγραμένου πίνακα\n" + +#: pg_dump.c:1072 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing προσθέστε ON CONFLICT DO NOTHING στις εντολές INSERT\n" + +#: pg_dump.c:1073 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers παράθεσε όλα τα αναγνωριστικά, ακόμα και αν δεν είναι λέξεις κλειδιά\n" + +#: pg_dump.c:1074 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS αριθμός γραμμών ανά INSERT; υπονοεί --inserts\n" + +#: pg_dump.c:1075 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION απόθεσε ονομασμένες ενότητες (προ-δεδομένα, δεδομένα, ή μετα-δεδομένα)\n" + +#: pg_dump.c:1076 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable ανάμενε έως ότου η απόθεση να μπορεί να τρέξει χωρίς ανωμαλίες\n" + +#: pg_dump.c:1077 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT χρησιμοποίησε το δοσμένο στιγμιότυπο για την απόθεση\n" + +#: pg_dump.c:1078 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names απαίτησε τα μοτίβα περίληψης πίνακα ή/και σχήματος να\n" +" αντιστοιχήσουν τουλάχιστον μία οντότητα το καθένα\n" + +#: pg_dump.c:1080 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" χρησιμοποιήσε τις εντολές SET SESSION AUTHORIZATION αντί των\n" +" ALTER OWNER για τον ορισμό ιδιοκτησίας\n" + +#: pg_dump.c:1084 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Επιλογές σύνδεσης:\n" + +#: pg_dump.c:1085 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME βάση δεδομένων για απόθεση\n" + +#: pg_dump.c:1086 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME διακομιστής βάσης δεδομένων ή κατάλογος υποδοχών\n" + +#: pg_dump.c:1087 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT θύρα διακομιστή βάσης δεδομένων\n" + +#: pg_dump.c:1088 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=USERNAME σύνδεση ως ο ορισμένος χρήστης βάσης δεδομένων\n" + +#: pg_dump.c:1089 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password να μην ζητείται ποτέ κωδικός πρόσβασης\n" + +#: pg_dump.c:1090 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password αναγκαστική προτροπή κωδικού πρόσβασης (πρέπει να συμβεί αυτόματα)\n" + +#: pg_dump.c:1091 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME κάνε SET ROLE πριν την απόθεση\n" + +#: pg_dump.c:1093 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Εάν δεν παρέχεται όνομα βάσης δεδομένων, τότε χρησιμοποιείται η μεταβλητή\n" +"περιβάλλοντος PGDATABASE.\n" +"\n" + +#: pg_dump.c:1095 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Υποβάλετε αναφορές σφάλματων σε <%s>.\n" + +#: pg_dump.c:1096 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s αρχική σελίδα: <%s>\n" + +#: pg_dump.c:1115 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "καθορίστηκε μη έγκυρη κωδικοποίηση προγράμματος-πελάτη «%s»" + +#: pg_dump.c:1261 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Τα συγχρονισμένα στιγμιότυπα σε διακομιστές αναμονής δεν υποστηρίζονται από αυτήν την έκδοση διακομιστή.\n" +"Εκτελέστε με --no-synchronized-snapshots, εάν δεν χρειάζεστε\n" +"συγχρονισμένα στιγμιότυπα." + +#: pg_dump.c:1330 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "ορίστηκε μη έγκυρη μορφή εξόδου «%s»" + +#: pg_dump.c:1368 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "δεν βρέθηκαν σχήματα που να ταιριάζουν με το μοτίβο «%s»" + +#: pg_dump.c:1415 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "δεν βρέθηκαν επεκτάσεις που ταιριάζουν με το μοτίβο «%s»" + +#: pg_dump.c:1462 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "δεν βρέθηκαν ξένοι διακομιστές που να ταιριάζουν με το μοτίβο «%s»" + +#: pg_dump.c:1525 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "δεν βρέθηκαν πίνακες που να ταιριάζουν για το μοτίβο «%s»" + +#: pg_dump.c:1948 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "αποθέτει τα δεδομένα του πίνακα «%s.%s»" + +#: pg_dump.c:2055 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Η απόθεση των περιεχομένων του πίνακα «%s» απέτυχε: PQgetCopyData() απέτυχε." + +#: pg_dump.c:2056 pg_dump.c:2066 +#, c-format +msgid "Error message from server: %s" +msgstr "Μήνυμα σφάλματος από διακομιστή: %s" + +#: pg_dump.c:2057 pg_dump.c:2067 +#, c-format +msgid "The command was: %s" +msgstr "Η εντολή ήταν: %s" + +#: pg_dump.c:2065 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Η απόθεση των περιεχομένων του πίνακα «%s» απέτυχε: PQgetResult() απέτυχε." + +#: pg_dump.c:2825 +#, c-format +msgid "saving database definition" +msgstr "αποθήκευση ορισμού βάσης δεδομένων" + +#: pg_dump.c:3297 +#, c-format +msgid "saving encoding = %s" +msgstr "αποθηκεύει encoding = %s" + +#: pg_dump.c:3322 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "αποθηκεύει standard_conforming_strings = %s" + +#: pg_dump.c:3361 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "δεν ήταν δυνατή η ανάλυση του αποτελέσματος της current_schemas()" + +#: pg_dump.c:3380 +#, c-format +msgid "saving search_path = %s" +msgstr "αποθηκεύει search_path = %s" + +#: pg_dump.c:3420 +#, c-format +msgid "reading large objects" +msgstr "ανάγνωση μεγάλων αντικειμένων" + +#: pg_dump.c:3602 +#, c-format +msgid "saving large objects" +msgstr "αποθηκεύει μεγάλων αντικειμένων" + +#: pg_dump.c:3648 +#, c-format +msgid "error reading large object %u: %s" +msgstr "σφάλμα κατά την ανάγνωση %u μεγάλου αντικειμένου: %s" + +#: pg_dump.c:3732 +#, c-format +msgid "reading row-level security policies" +msgstr "διαβάζει πολιτικές ασφαλείας επιπέδου σειράς" + +#: pg_dump.c:3875 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "μη αναμενόμενος τύπος εντολής πολιτικής: %c" + +#: pg_dump.c:4029 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "ο κάτοχος της δημοσίευσης «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:4321 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "οι συνδρομές δεν απορρίπτονται, επειδή ο τρέχων χρήστης δεν είναι υπερχρήστης" + +#: pg_dump.c:4392 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "ο κάτοχος της συνδρομής «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:4435 +#, c-format +msgid "could not parse subpublications array" +msgstr "δεν ήταν δυνατή η ανάλυση της συστοιχίας υποδημοσιεύσεων" + +#: pg_dump.c:4793 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "δεν ήταν δυνατή η εύρεση γονικής επέκτασης για %s %s" + +#: pg_dump.c:4925 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "ο κάτοχος του σχήματος «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:4948 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "το σχήμα με %u OID δεν υπάρχει" + +#: pg_dump.c:5278 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "ο κάτοχος του τύπου δεδομένων «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:5362 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "ο κάτοχος του χειριστή «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:5661 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "ο κάτοχος της κλάσης χειριστή «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:5744 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "ο κάτοχος της οικογένειας χειριστών «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:5912 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "ο κάτοχος της συνάρτησης συγκεντρωτικών αποτελεσμάτων «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:6171 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "ο κάτοχος της συνάρτησης «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:6998 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "ο κάτοχος του πίνακα «%s» φαίνεται να μην είναι έγκυρος" + +#: pg_dump.c:7040 pg_dump.c:17473 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "απέτυχε ο έλεγχος ακεραιότητας, ο γονικός πίνακας με OID %u της ακολουθίας με OID %u δεν βρέθηκε" + +#: pg_dump.c:7179 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "ανάγνωση ευρετηρίων για τον πίνακα «%s.%s»" + +#: pg_dump.c:7593 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "ανάγνωση περιορισμών ξένου κλειδιού για τον πίνακα «%s.%s»" + +#: pg_dump.c:7872 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "απέτυχε ο έλεγχος ακεραιότητας, ο γονικός πίνακας με OID %u της καταχώρησης pg_rewrite με OID %u δεν βρέθηκε" + +#: pg_dump.c:7956 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "ανάγνωση εναυσμάτων για τον πίνακα «%s.%s»" + +#: pg_dump.c:8138 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "το ερώτημα παρήγαγε null πίνακα αναφοράς για το έναυσμα ξένου κλειδιού «%s» στον πίνακα «%s» (OID του πίνακα: %u)" + +#: pg_dump.c:8688 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "εύρεση των στηλών και των τύπων του πίνακα «%s.%s»" + +#: pg_dump.c:8812 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "μη έγκυρη αρίθμηση στηλών στον πίνακα «%s»" + +#: pg_dump.c:8851 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "εύρεση προεπιλεγμένων εκφράσεων για τον πίνακα «%s.%s»" + +#: pg_dump.c:8873 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "μη έγκυρη τιμή adnum %d για τον πίνακα «%s»" + +#: pg_dump.c:8966 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "εύρεση περιορισμών ελέγχου για τον πίνακα «%s.%s»" + +#: pg_dump.c:9015 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "αναμενόμενος %d περιορισμός ελέγχου στον πίνακα «%s», αλλά βρήκε %d" +msgstr[1] "αναμενόμενοι %d περιορισμοί ελέγχου στον πίνακα «%s», αλλά βρήκε %d" + +#: pg_dump.c:9019 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Οι κατάλογοι συστήματος ενδέχεται να είναι αλλοιωμένοι.)" + +#: pg_dump.c:10621 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "typtype του τύπου δεδομένων «%s» φαίνεται να μην είναι έγκυρο" + +#: pg_dump.c:11969 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "πλαστή τιμή στη συστοιχία proargmodes" + +#: pg_dump.c:12271 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας proallargtypes" + +#: pg_dump.c:12287 +#, c-format +msgid "could not parse proargmodes array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας proargmodes" + +#: pg_dump.c:12301 +#, c-format +msgid "could not parse proargnames array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας proargnames" + +#: pg_dump.c:12311 +#, c-format +msgid "could not parse proconfig array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας proconfig" + +#: pg_dump.c:12387 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "μη αναγνωρίσιμη τιμή provolatile για τη συνάρτηση «%s»" + +#: pg_dump.c:12437 pg_dump.c:14378 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "μη αναγνωρίσιμη τιμή proparallel για τη συνάρτηση «%s»" + +#: pg_dump.c:12576 pg_dump.c:12682 pg_dump.c:12689 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "δεν ήταν δυνατή η εύρεση ορισμού συνάντησης για την συνάρτηση με OID %u" + +#: pg_dump.c:12615 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "πλαστή τιμή στο πεδίο pg_cast.castfunc ή pg_cast.castmethod" + +#: pg_dump.c:12618 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "πλαστή τιμή στο πεδίο pg_cast.castmethod" + +#: pg_dump.c:12708 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "πλαστός ορισμός μετασχηματισμού, τουλάχιστον μία από trffromsql και trftosql θα πρέπει να είναι μη μηδενική" + +#: pg_dump.c:12725 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "πλαστή τιμή στο πεδίο pg_transform.trffromsql" + +#: pg_dump.c:12746 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "πλαστή τιμή στο πεδίοpg_transform.trftosql" + +#: pg_dump.c:12897 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "χειριστές postfix δεν υποστηρίζεται πλέον (χειριστής «%s»)" + +#: pg_dump.c:13067 +#, c-format +msgid "could not find operator with OID %s" +msgstr "δεν ήταν δυνατή η εύρεση χειριστή με OID %s" + +#: pg_dump.c:13135 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "μη έγκυρος τύπος «%c» για την μεθόδο πρόσβασης «%s»" + +#: pg_dump.c:13889 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "μη αναγνωρίσιμος πάροχος συρραφής: %s" + +#: pg_dump.c:14297 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "μη αναγνωρίσιμη τιμή aggfinalmodify για το συγκεντρωτικό «%s»" + +#: pg_dump.c:14353 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "μη αναγνωρίσιμη τιμή aggmfinalmodify για το συγκεντρωτικό «%s»" + +#: pg_dump.c:15075 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "μη αναγνωρίσιμος τύπος αντικειμένου σε προεπιλεγμένα δικαιώματα: %d" + +#: pg_dump.c:15093 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "δεν ήταν δυνατή η ανάλυση της προεπιλεγμένης λίστας ACL (%s)" + +#: pg_dump.c:15178 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "δεν ήταν δυνατή η ανάλυση της αρχικής λίστας ACL GRANT (%s) ή της αρχικής λίστας REVOKE ACL (%s) για το αντικείμενο «%s» (%s)" + +#: pg_dump.c:15186 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "δεν ήταν δυνατή η ανάλυση της λίστας GRANT ACL (%s) ή της λίστας REVOKE ACL (%s) για το αντικείμενο «%s» (%s)" + +#: pg_dump.c:15701 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "το ερώτημα για τη λήψη ορισμού της όψης «%s» δεν επέστρεψε δεδομένα" + +#: pg_dump.c:15704 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "το ερώτημα για τη λήψη ορισμού της όψης «%s» επέστρεψε περισσότερους από έναν ορισμούς" + +#: pg_dump.c:15711 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "ο ορισμός της όψης «%s» φαίνεται να είναι κενός (μηδενικό μήκος)" + +#: pg_dump.c:15795 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS δεν υποστηρίζεται πλέον (πίνακας «%s»)" + +#: pg_dump.c:16660 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "μη έγκυρος αριθμός στήλης %d για τον πίνακα «%s»" + +#: pg_dump.c:16737 +#, c-format +msgid "could not parse index statistic columns" +msgstr "δεν ήταν δυνατή η ανάλυση στηλών στατιστικής ευρετηρίου" + +#: pg_dump.c:16739 +#, c-format +msgid "could not parse index statistic values" +msgstr "δεν ήταν δυνατή η ανάλυση ευρετηρίου στατιστικών τιμών" + +#: pg_dump.c:16741 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "ασυμφωνία αριθμού στηλών και τιμών για στατιστικά στοιχεία ευρετηρίου" + +#: pg_dump.c:16958 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "λείπει ευρετήριο για τον περιορισμό «%s»" + +#: pg_dump.c:17183 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "μη αναγνωρίσιμος τύπος περιορισμού: %c" + +#: pg_dump.c:17315 pg_dump.c:17538 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "ερώτημα για τη λήψη δεδομένων ακολουθίας «%s» επέστρεψε %d γραμμή (αναμένεται 1)" +msgstr[1] "ερώτημα για τη λήψη δεδομένων ακολουθίας «%s» επέστρεψε %d γραμμές (αναμένεται 1)" + +#: pg_dump.c:17349 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "μη αναγνωρίσιμος τύπος ακολουθίας: %s" + +#: pg_dump.c:17636 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "μη αναγνωρίσιμος τύπος tgtype: %d" + +#: pg_dump.c:17710 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "μη έγκυρη συμβολοσειρά παραμέτρου (%s) για το έναυσμα «%s» στον πίνακα «%s»" + +#: pg_dump.c:17979 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "ερώτημα για τη λήψη κανόνα «%s» για τον πίνακα «%s» απέτυχε: επιστράφηκε εσφαλμένος αριθμός γραμμών" + +#: pg_dump.c:18141 +#, c-format +msgid "could not find referenced extension %u" +msgstr "δεν ήταν δυνατή η εύρεση της αναφερόμενης επέκτασης %u" + +#: pg_dump.c:18232 +#, c-format +msgid "could not parse extension configuration array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας ρύθμισεων επέκτασης" + +#: pg_dump.c:18234 +#, c-format +msgid "could not parse extension condition array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας προϋποθέσεων επέκτασης" + +#: pg_dump.c:18236 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "ασυμφωνία αριθμού διαμορφώσεων και συνθηκών για επέκταση" + +#: pg_dump.c:18368 +#, c-format +msgid "reading dependency data" +msgstr "ανάγνωση δεδομένων εξάρτησης" + +#: pg_dump.c:18461 +#, c-format +msgid "no referencing object %u %u" +msgstr "δεν αναφέρεται αντικείμενο %u %u" + +#: pg_dump.c:18472 +#, c-format +msgid "no referenced object %u %u" +msgstr "μη αναφερόμενο αντικείμενο %u %u" + +#: pg_dump.c:18861 +#, c-format +msgid "could not parse reloptions array" +msgstr "δεν ήταν δυνατή η ανάλυση συστοιχίας reloptions" + +#: pg_dump_sort.c:411 +#, c-format +msgid "invalid dumpId %d" +msgstr "μη έγκυρο dumpId %d" + +#: pg_dump_sort.c:417 +#, c-format +msgid "invalid dependency %d" +msgstr "μη έγκυρη εξάρτηση %d" + +#: pg_dump_sort.c:650 +#, c-format +msgid "could not identify dependency loop" +msgstr "δεν ήταν δυνατός ο προσδιορισμός βρόχου εξάρτησης" + +#: pg_dump_sort.c:1221 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "υπάρχουν κυκλικοί περιορισμοί ξένου κλειδιού σε αυτόν τον πίνακα:" +msgstr[1] "υπάρχουν κυκλικοί περιορισμοί ξένου κλειδιού σε αυτούς τους πίνακες:" + +#: pg_dump_sort.c:1225 pg_dump_sort.c:1245 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1226 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Ενδέχεται να μην μπορείτε να επαναφέρετε την ένδειξη χωρίς να χρησιμοποιήσετε --disable-triggers ή να εγκαταλήψετε προσωρινά τους περιορισμούς." + +#: pg_dump_sort.c:1227 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Εξετάστε το ενδεχόμενο να χρησιμοποιήσετε μια πλήρη απόθεση αντί για μια --data-only απόθεση για να αποφύγετε αυτό το πρόβλημα." + +#: pg_dump_sort.c:1239 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "δεν ήταν δυνατή η επίλυση του βρόχου εξάρτησης μεταξύ αυτών των στοιχείων:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Το πρόγραμμα «%s» απαιτείται από %s αλλά δεν βρέθηκε στον\n" +"ίδιο κατάλογο με το «%s».\n" +"Ελέγξτε την εγκατάστασή σας." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Το πρόγραμμα «%s» βρέθηκε από το \"%s\"\n" +"αλλά δεν ήταν η ίδια εκδοχή με %s.\n" +"Ελέγξτε την εγκατάστασή σας." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "επιλογή --exclude-database δεν μπορεί να χρησιμοποιηθεί μαζί με -g/--globals-only, -r/--roles-only, ή -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "οι επιλογές -g/--globals-only και -r/--roles-only δεν μπορούν να χρησιμοποιηθούν μαζί" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "οι επιλογές -g/--globals-only μόνο και -t/--tablespaces-only δεν είναι δυνατό να χρησιμοποιηθούν μαζί" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "οι επιλογές -r/--roles-only και -t/--tablespaces-only δεν μπορούν να χρησιμοποιηθούν μαζί" + +#: pg_dumpall.c:453 pg_dumpall.c:1756 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "δεν ήταν δυνατή η σύνδεση στη βάση δεδομένων «%s»" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"δεν ήταν δυνατή η σύνδεση με τις βάσεις δεδομένων \"postgres\" ή \"Template1\"\n" +"Παρακαλώ καθορίστε μία εναλλακτική βάση δεδομένων." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s εξάγει μία συστάδα βάσεων δεδομένων PostgreSQL σε ένα αρχείο σεναρίου SQL.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [ΕΠΙΛΟΓΗ]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=FILENAME όνομα αρχείου εξόδου\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean καθάρισε (εγκατάληψε) βάσεις δεδομένων πριν από την αναδημιουργία\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only απόθεσε μόνο καθολικά αντικείμενα, όχι βάσεις δεδομένων\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner παράλειψε την αποκατάσταση της κυριότητας αντικειμένων\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only απόθεσε μόνο ρόλους, όχι βάσεις δεδομένων ή πινακοχώρους\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME όνομα υπερχρήστη για να χρησιμοποιηθεί στην απόθεση\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only απόθεσε μόνο πινακοχώρους, όχι βάσεις δεδομένων ή ρόλους\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=PATTERN εξαίρεσε βάσεις δεδομένων των οποίων το όνομα ταιριάζει με PATTERN\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords να μην αποθέσει κωδικούς πρόσβασης για ρόλους\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR σύνδεση με χρήση συμβολοσειράς σύνδεσης\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr "" +" -l, --database=DBNAME εναλλακτική προεπιλεγμένη βάση δεδομένων\n" +"\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Εάν δεν χρησιμοποιηθεί -f/--file , τότε η δέσμη ενεργειών SQL θα εγγραφεί στη τυπική\n" +"έξοδο.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "όνομα ρόλου που αρχίζει «pg_» παραλείπεται (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "δεν ήταν δυνατή η ανάλυση της λίστας ACL (%s) για τον πινακοχώρο «%s»" + +#: pg_dumpall.c:1501 +#, c-format +msgid "excluding database \"%s\"" +msgstr "εξαιρεί τη βάση δεδομένων «%s»" + +#: pg_dumpall.c:1505 +#, c-format +msgid "dumping database \"%s\"" +msgstr "αποθέτει τη βάση δεδομένων «%s»" + +#: pg_dumpall.c:1537 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump απέτυχε στη βάση δεδομένων «%s», εξέρχεται" + +#: pg_dumpall.c:1546 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "δεν ήταν δυνατό το εκ νέου άνοιγμα του αρχείου εξόδου «%s»: %m" + +#: pg_dumpall.c:1590 +#, c-format +msgid "running \"%s\"" +msgstr "εκτελείται «%s»" + +#: pg_dumpall.c:1805 +#, c-format +msgid "could not get server version" +msgstr "δεν ήταν δυνατή η απόκτηση έκδοσης διακομιστή" + +#: pg_dumpall.c:1811 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "δεν ήταν δυνατή η ανάλυση έκδοσης διακομιστή «%s»" + +#: pg_dumpall.c:1883 pg_dumpall.c:1906 +#, c-format +msgid "executing %s" +msgstr "εκτελείται %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "ένα από τα -d/--dbname και -f/--file πρέπει να καθοριστεί" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "οι επιλογές -d/--dbname και -f/--file δεν μπορούν να χρησιμοποιηθούν μαζί" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "οι επιλογές -C/--create και -1/--single-transaction δεν μπορούν να χρησιμοποιηθούν μαζί" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "ο μέγιστος αριθμός παράλληλων εργασιών είναι %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "δεν είναι δυνατό να οριστούν μαζί --single-transaction και multiple jobs" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "μη αναγνωρισμένη μορφή αρχειοθέτησης «%s»· παρακαλώ καθορίστε «c», «d» ή «t»" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "σφάλματα που παραβλέφθηκαν κατά την επαναφορά: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s επαναφέρει μια βάση δεδομένων PostgreSQL από μια αρχειοθήκη που δημιουργήθηκε από τη pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [ΕΠΙΛΟΓΗ]... [ΑΡΧΕΙΟ]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME σύνδεση με τη βάσης δεδομένων με όνομα\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FILENAME όνομα αρχείου εξόδου (- για stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t μορφή αρχείου αντιγράφου ασφαλείας (θα πρέπει να είναι αυτόματη)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list εκτύπωσε συνοπτικό TOC της αρχειοθήκης\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose περιφραστική λειτουργία\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version εμφάνισε πληροφορίες έκδοσης, στη συνέχεια έξοδος\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help εμφάνισε αυτό το μήνυμα βοήθειας, στη συνέχεια έξοδος\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Επιλογές που ελέγχουν την επαναφορά:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only επαναφέρε μόνο τα δεδομένα, όχι το σχήμα\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create δημιούργησε τη βάσης δεδομένων προορισμού\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error να εξέλθει σε σφάλμα, η προεπιλογή είναι να συνεχίσει\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME επανάφερε το ευρετήριο με όνομα\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM χρησιμοποίησε τόσες πολλές παράλληλες εργασίες για την επαναφορά\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FILENAME χρησιμοποίησε τον πίνακα περιεχομένων από αυτό το αρχείο για\n" +" επιλογή/ταξινόμηση εξόδου\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME επανάφερε μόνο αντικείμενα σε αυτό το σχήμα\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME να μην επαναφέρει αντικείμενα από αυτό το σχήμα\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) επανάφερε την καθορισμένη συνάρτηση\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only επανάφερε μόνο το σχήμα, χωρίς δεδομένα\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAME όνομα υπερχρήστη για χρήση κατά την απενεργοποίηση εναυσμάτων\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NAME επανάφερε την καθορισμένη σχέση (πίνακας, προβολή κ.λπ.)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr "" +" -T, --trigger=NAME επανάφερε το καθορισμένο έναυσμα\n" +"\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges παράλειπε την επαναφορά των δικαιωμάτων πρόσβασης (εκχώρηση/ανάκληση)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction επανάφερε ως μεμονωμένη συναλλαγή\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security ενεργοποίησε ασφαλεία σειράς\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments να μην επαναφέρεις σχόλια\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables να μην επαναφέρεις δεδομένα πινάκων που δεν ήταν\n" +" δυνατό να δημιουργήθουν\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications να μην επαναφέρεις δημοσιεύσεις\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels να μην επαναφέρεις ετικέτες ασφαλείας\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-publications να μην επαναφέρεις συνδρομές\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces να μην επαναφέρεις αναθέσεις πινακοχώρων\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION επανάφερε ονομασμένες ενότητες (προ-δεδομένα, δεδομένα, ή μετα-δεδομένα)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME κάνε SET ROLE πριν την επαναφορά\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Οι επιλογές -I, -n, -N, -P, -t, -T και --section μπορούν να συνδυαστούν και να καθοριστούν\n" +"πολλές φορές για την επιλογή πολλών αντικειμένων.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Εάν δεν παρέχεται όνομα αρχείου εισόδου, τότε χρησιμοποιείται η τυπική είσοδος.\n" +"\n" + +#~ msgid "could not connect to database \"%s\": %s" +#~ msgstr "δεν ήταν δυνατή η σύνδεση στη βάση δεδομένων «%s»: %s" + +#~ msgid "aggregate function %s could not be dumped correctly for this database version; ignored" +#~ msgstr "δεν ήταν δυνατή η σωστή απόθεση της συνάρτησης συγκεντρωτικών αποτελεσμάτων %s για αυτήν την έκδοση της βάσης δεδομένων· παραβλέπεται" + +#~ msgid "connection to database \"%s\" failed: %s" +#~ msgstr "σύνδεση στη βάση δεδομένων «%s» απέτυχε: %s" + +#~ msgid "could not write to large object (result: %lu, expected: %lu)" +#~ msgstr "δεν ήταν δυνατή η εγγραφή σε μεγάλο αντικείμενο (αποτέλεσμα: %lu, αναμένεται: %lu)" + +#~ msgid "select() failed: %m" +#~ msgstr "απέτυχε το select(): %m" + +#~ msgid "WSAStartup failed: %d" +#~ msgstr "WSAStartup απέτυχε: %d" + +#~ msgid "pclose failed: %m" +#~ msgstr "απέτυχε η εντολή pclose: %m" + +#~ msgid "reading policies for table \"%s.%s\"" +#~ msgstr "ανάγνωση πολιτικών για τον πίνακα «%s.%s»" + +#~ msgid "reading row security enabled for table \"%s.%s\"" +#~ msgstr "ανάγνωση ενεργοποιημένης ασφάλειας γραμμής για τον πίνακα «%s.%s»" diff --git a/src/bin/pg_dump/po/es.po b/src/bin/pg_dump/po/es.po new file mode 100644 index 0000000..a70b861 --- /dev/null +++ b/src/bin/pg_dump/po/es.po @@ -0,0 +1,2757 @@ +# Spanish message translation file for pg_dump +# +# Copyright (c) 2003-2021, PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# +# Manuel Sugawara , 2003. +# Alvaro Herrera , 2004-2007, 2009-2013 +# Carlos Chapi , 2014, 2017, 2021 +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL) 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-08-07 20:35+0000\n" +"PO-Revision-Date: 2022-01-12 17:37-0500\n" +"Last-Translator: Carlos Chapi \n" +"Language-Team: PgSQL-es-Ayuda \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: BlackCAT 1.1\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "fatal: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "error: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "precaución: " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "no se pudo identificar el directorio actual: %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "el binario «%s» no es válido" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "no se pudo leer el binario «%s»" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "no se pudo encontrar un «%s» para ejecutar" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "no se pudo cambiar al directorio «%s»: %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "no se pudo leer el enlace simbólico «%s»: %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() falló: %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "memoria agotada" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "la orden no es ejecutable" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "orden no encontrada" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "el proceso hijo terminó con código de salida %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "el proceso hijo fue terminado por una excepción 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "el proceso hijo fue terminado por una señal %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "el proceso hijo terminó con código no reconocido %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "leyendo las extensiones" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "identificando miembros de extensión" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "leyendo esquemas" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "leyendo las tablas definidas por el usuario" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "leyendo las funciones definidas por el usuario" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "leyendo los tipos definidos por el usuario" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "leyendo los lenguajes procedurales" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "leyendo las funciones de agregación definidas por el usuario" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "leyendo los operadores definidos por el usuario" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "leyendo los métodos de acceso definidos por el usuario" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "leyendo las clases de operadores definidos por el usuario" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "leyendo las familias de operadores definidas por el usuario" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "leyendo los procesadores (parsers) de búsqueda en texto definidos por el usuario" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "leyendo las plantillas de búsqueda en texto definidas por el usuario" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "leyendo los diccionarios de búsqueda en texto definidos por el usuario" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "leyendo las configuraciones de búsqueda en texto definidas por el usuario" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "leyendo los conectores de datos externos definidos por el usuario" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "leyendo los servidores foráneos definidas por el usuario" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "leyendo los privilegios por omisión" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "leyendo los ordenamientos definidos por el usuario" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "leyendo las conversiones definidas por el usuario" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "leyendo conversiones de tipo" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "leyendo las transformaciones" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "leyendo la información de herencia de las tablas" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "leyendo los disparadores por eventos" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "buscando tablas de extensión" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "buscando relaciones de herencia" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "leyendo la información de columnas para las tablas interesantes" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "marcando las columnas heredadas en las subtablas" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "leyendo los índices" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "marcando índices en las tablas particionadas" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "leyendo estadísticas extendidas" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "leyendo las restricciones" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "leyendo los disparadores (triggers)" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "leyendo las reglas de reescritura" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "leyendo políticas" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "leyendo publicaciones" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "leyendo membresía en publicaciones" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "leyendo las suscripciones" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "número de padres %d para la tabla «%s» no es válido" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "falló la revisión de integridad, el OID %u del padre de la tabla «%s» (OID %u) no se encontró" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "no se pudo interpretar el arreglo numérico «%s»: demasiados números" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "no se pudo interpretar el arreglo numérico «%s»: carácter no válido en número" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "código de compresión no válido: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "no contiene soporte zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "no se pudo inicializar la biblioteca de compresión: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "no se pudo cerrar el flujo comprimido: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "no se pudo comprimir datos: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "no se pudo descomprimir datos: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "no se pudo cerrar la biblioteca de compresión: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "no se pudo leer el archivo de entrada: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "no se pudo leer desde el archivo de entrada: fin de archivo" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s() falló: código de error %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "no se pudo crear los canales de comunicación: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "no se pudo crear el proceso hijo: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "orden no reconocida recibida del servidor principal: «%s»" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "mensaje no válido recibido del proceso hijo: «%s»" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"no se pudo obtener un lock en la relación «%s»\n" +"Esto normalmente significa que alguien solicitó un lock ACCESS EXCLUSIVE en la tabla después de que el proceso pg_dump padre había obtenido el lock ACCESS SHARE en la tabla." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "un proceso hijo murió inesperadamente" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "no se pudo escribir al canal de comunicación: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: no se pudo crear el socket: código de error %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: no se pudo enlazar: código de error %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: no se pudo escuchar: código de error %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s() falló: código de error %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: no se pudo crear el segundo socket: código de error %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: no se pudo conectar el socket: código de error %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: no se pudo aceptar la conexión: código de error %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "no se pudo cerrar el archivo de salida: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "elementos del archivo no están en el orden correcto de secciones" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "código de sección %d inesperado" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "la restauración en paralelo no está soportada con este formato de archivo" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "la restauración en paralelo no está soportada con archivos construidos con pg_dump anterior a 8.0" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "no se puede reestablecer desde un archivo comprimido (la compresión no está soportada en esta instalación)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "conectando a la base de datos para reestablecimiento" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "las conexiones directas a la base de datos no están soportadas en archivadores pre-1.3" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "asumiendo reestablecimiento de sólo datos" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "eliminando %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "no se pudo encontrar dónde insertar IF EXISTS en la sentencia «%s»" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "precaución desde el archivo original: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "creando %s «%s.%s»" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "creando %s «%s»" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "conectando a nueva base de datos «%s»" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "procesando %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "procesando datos de la tabla «%s.%s»" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "ejecutando %s %s" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "deshabilitando disparadores (triggers) para %s" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "habilitando disparadores (triggers) para %s" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "error interno -- WriteData no puede ser llamada fuera del contexto de una rutina DataDumper" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "la extracción de objetos grandes no está soportada en el formato seleccionado" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "se reestableció %d objeto grande" +msgstr[1] "se reestablecieron %d objetos grandes" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "reestableciendo objeto grande con OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "no se pudo crear el objeto grande %u: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "no se pudo abrir el objeto grande %u: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "no se pudo abrir el archivo TOC «%s»: %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "línea ignorada: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "no se pudo encontrar una entrada para el ID %d" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "no se pudo cerrar el archivo TOC: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "no se pudo abrir el archivo de salida «%s»: %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "no se pudo abrir el archivo de salida: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "se escribió %zu byte de los datos del objeto grande (resultado = %d)" +msgstr[1] "se escribieron %zu bytes de los datos del objeto grande (resultado = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "no se pudo escribir en objeto grande: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "durante INICIALIZACIÓN:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "durante PROCESAMIENTO DE TABLA DE CONTENIDOS:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "durante FINALIZACIÓN:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "en entrada de la tabla de contenidos %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "dumpId incorrecto" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "dumpId de tabla incorrecto para elemento TABLE DATA" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "bandera de posición inesperada %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "el posición en el archivo es demasiado grande" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "nombre de directorio demasiado largo: «%s»" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "el directorio «%s» no parece ser un archivador válido (no existe «toc.dat»)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "no se pudo abrir el archivo de entrada «%s»: %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "no se pudo abrir el archivo de entrada: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "no se pudo leer el archivo de entrada: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "el archivo de entrada es demasiado corto (leidos %lu, esperados 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "el archivo de entrada parece ser un volcado de texto. Por favor use psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "el archivo de entrada no parece ser un archivador válido (¿demasiado corto?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "el archivo de entrada no parece ser un archivador válido" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "no se pudo cerrar el archivo de entrada: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "formato de archivo no reconocido «%d»" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "terminó el elemento %d %s %s" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "el proceso hijo falló: código de salida %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "la entrada con ID %d está fuera de rango -- tal vez la tabla de contenido está corrupta" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "restaurar tablas WITH OIDS ya no está soportado" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "no se reconoce la codificación: «%s»" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "elemento ENCODING no válido: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "elemento STDSTRINGS no válido: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "esquema «%s» no encontrado" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "tabla «%s» no encontrada" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "índice «%s» no encontrado" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "función «%s» no encontrada" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "disparador «%s» no encontrado" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "no se pudo establecer el usuario de sesión a «%s»: %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "no se pudo definir search_path a «%s»: %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "no se pudo definir default_tablespace a %s: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "no se pudo definir default_table_access_method: %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "no se sabe cómo establecer el dueño para el objeto de tipo «%s»" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "no se encontró la cadena mágica en el encabezado del archivo" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "versión no soportada (%d.%d) en el encabezado del archivo" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "revisión de integridad en el tamaño del entero (%lu) falló" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "el archivador fue hecho en una máquina con enteros más grandes, algunas operaciones podrían fallar" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "el formato esperado (%d) difiere del formato encontrado en el archivo (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "el archivador está comprimido, pero esta instalación no soporta compresión -- no habrá datos disponibles" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "la fecha de creación en el encabezado no es válida" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "procesando el elemento %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "ingresando al bucle paralelo principal" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "saltando el elemento %d %s %s" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "lanzando el elemento %d %s %s" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "terminó el bucle paralelo principal" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "procesando el elemento saltado %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "la tabla «%s» no pudo ser creada, no se recuperarán sus datos" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "OID no válido para objeto grande" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "error durante el posicionamiento (seek) en el archivo: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "el bloque de datos %d tiene una posición de búsqueda incorrecta" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "tipo de bloque de datos (%d) no conocido al buscar en el archivador" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "no se pudo encontrar el bloque con ID %d en archivo -- posiblemente debido a una petición de restauración fuera de orden, la que no puede ser completada debido a que en el archivo de entrada no es reposicionable (seekable)" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "no se pudo encontrar el bloque con ID %d en archivo -- posiblemente el archivo está corrupto" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "se encontró un bloque no esperado ID (%d) mientras se leían los datos -- se esperaba %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "se encontró un bloque tipo %d no reconocido al restablecer el archivador" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "no se pudo leer el archivo de entrada: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "no se pudo determinar la posición (seek) en el archivo del archivador: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "no se pudo cerrar el archivo del archivador: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "sólo se pueden reabrir archivos de entrada" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "la restauración en paralelo desde entrada estándar (stdin) no está soportada" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "la restauración en paralelo desde un archivo no posicionable no está soportada" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "no se pudo posicionar (seek) en el archivo del archivador: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "compresor activo" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "no se pudo obtener server_version desde libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "versión del servidor: %s; versión de %s: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "abortando debido a que no coincide la versión del servidor" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "ya está conectado a una base de datos" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Contraseña: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "no se pudo hacer la conexión a la base de datos" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "falló la reconexión: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "la consulta falló: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "la consulta era: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "la consulta regresó %d fila en lugar de una: %s" +msgstr[1] "la consulta regresó %d filas en lugar de una: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sLa orden era: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "no se pudo ejecutar la consulta" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "PQputCopyData regresó un error: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "PQputCopyEnd regresó un error: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY falló para la tabla «%s»: %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "resultados extra inesperados durante el COPY de la tabla «%s»" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "no se pudo iniciar la transacción en la base de datos" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "no se pudo terminar la transacción a la base de datos" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "no se especificó un directorio de salida" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "no se pudo crear el directorio «%s»: %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "no se pudo escribir al archivo de salida: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "no se pudo cerrar el archivo de datos: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "no se pudo cerrar el archivo de datos «%s»: %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "no se pudo abrir el archivo de la tabla de contenidos de objetos grandes «%s» para su lectura: %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "línea no válida en el archivo de la tabla de contenido de objetos grandes «%s»: «%s»" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "error al leer el archivo de la tabla de contenidos de objetos grandes «%s»" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "no se pudo cerrar el archivo de la tabla de contenido de los objetos grandes «%s»: %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "no se pudo cerrar el archivo de datos de objetos grandes: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "no se pudo escribir al archivo de la tabla de contenidos de objetos grandes" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "no se pudo cerrar el archivo de la tabla de contenidos de objetos grandes: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "nombre de archivo demasiado largo: «%s»" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "no se puede leer este formato" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "no se pudo abrir el archivo de tabla de contenido «%s» para escribir: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "no se pudo abrir la tabla de contenido para escribir: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "la compresión no está soportada por el formato de salida tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "no se pudo abrir el archivo de tabla de contenido «%s» para leer: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "no se pudo abrir la tabla de contenido para leer: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "no se pudo encontrar el archivo «%s» en el archivador" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "no se pudo generar el nombre de archivo temporal: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "no se pudo abrir archivo temporal" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "no se pudo cerrar miembro del archivo tar: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "sintaxis de sentencia COPY inesperada: «%s»" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "el OID del objeto grande no es válido (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "no se pudo abrir archivo temporal: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "el tamaño real del archivo (%s) no coincide con el esperado (%s)" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "no se pudo encontrar el encabezado para el archivo «%s» en el archivo tar" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "la extracción de datos fuera de orden no está soportada en este formato: se requiere «%s», pero viene antes de «%s» en el archivador." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "se encontró un encabezado incompleto (%lu byte)" +msgstr[1] "se encontró un encabezado incompleto (%lu bytes)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "se encontró un encabezado corrupto en %s (esperado %d, calculado %d) en la posición %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "nombre de sección «%s» no reconocido" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Prueba «%s --help» para más información.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "elementos on_exit_nicely agotados" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "nivel de compresión debe estar en el rango 0..9" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_floats_digits debe estar en el rango -15..3" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert debe estar en el rango %d..%d" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "las opciones -s/--schema-only y -a/--data-only no pueden usarse juntas" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "las opciones -s/--schema-only y --include-foreign-data no pueden usarse juntas" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "la opción --include-foreign-data no está soportado con respaldo en paralelo" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "las opciones -c/--clean y -a/--data-only no pueden usarse juntas" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "la opción --if-exists requiere la opción -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "la opción --on-conflict-do-nothing requiere la opción --inserts, --rows-per-insert o --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "la compresión solicitada no está soportada en esta instalación -- el archivador será sin compresión" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "número no válido de trabajos paralelos" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "el volcado en paralelo sólo está soportado por el formato «directory»" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Los snapshots sincronizados no están soportados por esta versión del servidor.\n" +"Ejecute con --no-synchronized-snapshots si no los necesita." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Los snapshot exportados no están soportados por esta versión de servidor." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "el último OID interno es %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "no se encontraron esquemas coincidentes" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "no se encontraron tablas coincidentes" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "no se encontraron extensiones coincidentes" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s extrae una base de datos en formato de texto o en otros formatos.\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Empleo:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [OPCIÓN]... [NOMBREDB]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Opciones generales:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=ARCHIVO nombre del archivo o directorio de salida\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p Formato del archivo de salida (c=personalizado, \n" +" d=directorio, t=tar, p=texto (por omisión))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM máximo de procesos paralelos para volcar\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose modo verboso\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de version y salir\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 nivel de compresión para formatos comprimidos\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=SEGS espera a lo más SEGS segundos obtener un lock\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync no esperar que los cambios se sincronicen a disco\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda y salir\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Opciones que controlan el contenido de la salida:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only extrae sólo los datos, no el esquema\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs incluye objetos grandes en la extracción\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs excluye objetos grandes en la extracción\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean tira (drop) la base de datos antes de crearla\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr "" +" -C, --create incluye órdenes para crear la base de datos\n" +" en la extracción\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=PATRÓN extrae sólo la o las extensiones nombradas\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=CODIF extrae los datos con la codificación CODIF\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATRÓN extrae sólo el o los esquemas nombrados\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATRÓN NO extrae el o los esquemas nombrados\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner en formato de sólo texto, no reestablece\n" +" los dueños de los objetos\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only extrae sólo el esquema, no los datos\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME superusuario a utilizar en el volcado de texto\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATRÓN extrae sólo la o las tablas nombradas\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATRÓN NO extrae la o las tablas nombradas\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges no extrae los privilegios (grant/revoke)\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade sólo para uso de utilidades de upgrade\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr "" +" --column-inserts extrae los datos usando INSERT con nombres\n" +" de columnas\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr "" +" --disable-dollar-quoting deshabilita el uso de «delimitadores de dólar»,\n" +" usa delimitadores de cadena estándares\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr "" +" --disable-triggers deshabilita los disparadores (triggers) durante el\n" +" restablecimiento de la extracción de sólo-datos\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security activa seguridad de filas (volcar sólo el\n" +" contenido al que el usuario tiene acceso)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATRÓN NO extrae los datos de la(s) tablas nombradas\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM usa este valor para extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists usa IF EXISTS al eliminar objetos\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=PATRÓN\n" +" incluye datos de tablas foráneas en servidores\n" +" que coinciden con PATRÓN\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts extrae los datos usando INSERT, en vez de COPY\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root cargar particiones a través de tabla raíz\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments no volcar los comentarios\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications no volcar las publicaciones\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels no volcar asignaciones de etiquetas de seguridad\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions no volcar las suscripciones\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr "" +" --no-synchronized-snapshots no usar snapshots sincronizados en trabajos\n" +" en paralelo\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces no volcar asignaciones de tablespace\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression no volcar métodos de compresión TOAST\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data no volcar datos de tablas unlogged\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing agregar ON CONFLICT DO NOTHING a órdenes INSERT\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers entrecomilla todos los identificadores, incluso\n" +" si no son palabras clave\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NUMFILAS número de filas por INSERT; implica --inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECCIÓN volcar la sección nombrada (pre-data, data,\n" +" post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr "" +" --serializable-deferrable espera hasta que el respaldo pueda completarse\n" +" sin anomalías\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT use el snapshot dado para la extracción\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names requerir al menos una coincidencia para cada patrón\n" +" de nombre de tablas y esquemas\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" usa órdenes SESSION AUTHORIZATION en lugar de\n" +" ALTER OWNER para cambiar los dueño de los objetos\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Opciones de conexión:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=NOMBRE nombre de la base de datos que volcar\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr "" +" -h, --host=ANFITRIÓN anfitrión de la base de datos o\n" +" directorio del enchufe (socket)\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PUERTO número del puerto de la base de datos\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=USUARIO nombre de usuario con el cual conectarse\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password nunca pedir una contraseña\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr "" +" -W, --password fuerza un prompt para la contraseña\n" +" (debería ser automático)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROL ejecuta SET ROLE antes del volcado\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Si no se especifica un nombre de base de datos, se utiliza el valor\n" +"de la variable de ambiente PGDATABASE.\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Reporte errores a <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Sitio web de %s: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "la codificación de cliente especificada «%s» no es válida" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Los snapshots sincronizados en servidores standby no están soportados por esta versión del servidor.\n" +"Ejecute con --no-synchronized-snapshots si no los necesita." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "el formato de salida especificado «%s» no es válido" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "el nombre no es válido (demasiados puntos): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "no se encontraron esquemas coincidentes para el patrón «%s»" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "no se encontraron extensiones coincidentes para el patrón «%s»" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "no se encontraron servidores foráneos coincidentes para el patrón «%s»" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "el nombre de relación no es válido (demasiados puntos): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "no se encontraron tablas coincidentes para el patrón «%s»" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "No está conectado a una base de datos." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "no están implementadas las referencias entre bases de datos: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "extrayendo el contenido de la tabla «%s.%s»" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Falló la extracción del contenido de la tabla «%s»: PQgetCopyData() falló." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Mensaje de error del servidor: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "La orden era: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Falló la extracción del contenido de la tabla «%s»: PQgetResult() falló." + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "se obtuvo un número incorrecto de campos de la tabla «%s»" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "salvando las definiciones de la base de datos" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "salvando codificaciones = %s" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "salvando standard_conforming_strings = %s" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "no se pudo interpretar la salida de current_schemas()" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "salvando search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "leyendo objetos grandes" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "salvando objetos grandes" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "error al leer el objeto grande %u: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "leyendo políticas de seguridad a nivel de registros" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "tipo de orden inesperada en política: %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "el dueño de la publicación «%s» parece no ser válido" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "no se volcaron las suscripciones porque el usuario actual no es un superusuario" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "el dueño de la suscripción «%s» parece no ser válido" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "no se pudo interpretar el arreglo subpublications" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "no se pudo encontrar la extensión padre para %s %s" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "el dueño del esquema «%s» parece no ser válido" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "no existe el esquema con OID %u" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "el dueño del tipo «%s» parece no ser válido" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "el dueño del operador «%s» parece no ser válido" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "el dueño de la clase de operadores «%s» parece no ser válido" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "el dueño de la familia de operadores «%s» parece no ser válido" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "el dueño de la función de agregación «%s» parece no ser válido" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "el dueño de la función «%s» parece no ser válido" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "el dueño de la tabla «%s» parece no ser válido" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "falló la revisión de integridad, no se encontró la tabla padre con OID %u de la secuencia con OID %u" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "extrayendo los índices para la tabla «%s.%s»" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "extrayendo restricciones de llave foránea para la tabla «%s.%s»" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "falló la revisión de integridad, no se encontró la tabla padre con OID %u del elemento con OID %u de pg_rewrite" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "extrayendo los disparadores (triggers) para la tabla «%s.%s»" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "la consulta produjo un nombre de tabla nulo para la llave foránea del disparador \"%s\" en la tabla «%s» (OID de la tabla: %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "buscando las columnas y tipos de la tabla «%s.%s»" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "numeración de columnas no válida en la tabla «%s»" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "buscando expresiones por omisión de la tabla «%s.%s»" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "el valor de adnum %d para la tabla «%s» no es válido" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "buscando restricciones de revisión (check) para la tabla «%s.%s»" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "se esperaban %d restricciones CHECK en la tabla «%s» pero se encontraron %d" +msgstr[1] "se esperaban %d restricciones CHECK en la tabla «%s» pero se encontraron %d" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Los catálogos del sistema podrían estar corruptos)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "el typtype del tipo «%s» parece no ser válido" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "valor no válido en el arreglo proargmodes" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "no se pudo interpretar el arreglo proallargtypes" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "no se pudo interpretar el arreglo proargmodes" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "no se pudo interpretar el arreglo proargnames" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "no se pudo interpretar el arreglo proconfig" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "el valor del atributo «provolatile» para la función «%s» es desconocido" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "el valor del atributo «proparallel» para la función «%s» es desconocido" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "no se encontró la definición de la función con OID %u" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "valor no válido en los campos pg_cast.castfunc o pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "valor no válido en el campo pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "definición errónea de transformación; al menos uno de trffromsql and trftosql debe ser distinto de cero" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "valor erróneo en el campo pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "valor erróneo en el campo pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "los operadores postfix ya no están soportados (operador «%s»)" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "no se pudo encontrar el operador con OID %s" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "el tipo «%c» para el método de acceso «%s» no es válido" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "proveedor de ordenamiento no reconocido: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "valor de aggfinalmodify no reconocido para la agregación «%s»" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "valor de aggmfinalmodify no reconocido para la agregación «%s»" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "tipo de objeto desconocido en privilegios por omisión: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "no se pudo interpretar la lista de ACL (%s)" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "no se pudo interpretar la lista inicial de GRANT ACL (%s) o la lista inicial de REVOKE ACL (%s) para el objeto «%s» (%s)" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "no se pudo interpretar la lista de GRANT ACL (%s) o la lista de REVOKE ACL (%s) para el objeto «%s» (%s)" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "la consulta para obtener la definición de la vista «%s» no regresó datos" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "la consulta para obtener la definición de la vista «%s» regresó más de una definición" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "la definición de la vista «%s» parece estar vacía (tamaño cero)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS ya no está soportado (tabla «%s»)" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "el número de columna %d no es válido para la tabla «%s»" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "no se pudieron interpretar columnas de estadísticas de índices" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "no se pudieron interpretar valores de estadísticas de índices" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "no coincide el número de columnas con el de valores para estadísticas de índices" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "falta un índice para restricción «%s»" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "tipo de restricción inesperado: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "la consulta para obtener los datos de la secuencia «%s» regresó %d entrada, pero se esperaba 1" +msgstr[1] "la consulta para obtener los datos de la secuencia «%s» regresó %d entradas, pero se esperaba 1" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "tipo no reconocido de secuencia: %s" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "tgtype no esperado: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "argumento de cadena (%s) no válido para el disparador (trigger) «%s» en la tabla «%s»" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "la consulta para obtener la regla «%s» asociada con la tabla «%s» falló: retornó un número incorrecto de renglones" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "no se pudo encontrar la extensión referenciada %u" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "no se pudo interpretar el arreglo de configuración de extensión" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "no se pudo interpretar el arreglo de condición de extensión" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "no coincide el número de configuraciones con el de condiciones para extensión" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "obteniendo datos de dependencias" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "no existe el objeto referenciante %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "no existe el objeto referenciado %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "no se pudo interpretar el arreglo reloptions" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "dumpId %d no válido" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "dependencia %d no válida" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "no se pudo identificar bucle de dependencia" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "hay restricciones de llave foránea circulares en la siguiente tabla:" +msgstr[1] "hay restricciones de llave foránea circulares entre las siguientes tablas:" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Puede no ser capaz de restaurar el respaldo sin usar --disable-triggers o temporalmente eliminar las restricciones." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Considere usar un volcado completo en lugar de --data-only para evitar este problema." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "no se pudo resolver el bucle de dependencias entre los siguientes elementos:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"%s necesita el programa «%s» pero no fue encontrado en el\n" +"mismo directorio que «%s».\n" +"Verifique su instalación." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"El programa «%s» fue encontrado por «%s»\n" +"but no era de la misma versión que %s.\n" +"Verifique su instalación." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "la opción --exclude-database no puede ser usada junto con -g/--globals-only, -r/--roles-only o -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "las opciones -g/--globals-only y -r/--roles-only no pueden usarse juntas" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "las opciones -g/--globals-only y -t/--tablespaces-only no pueden usarse juntas" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "las opciones -r/--roles-only y -t/--tablespaces-only no pueden usarse juntas" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "no se pudo establecer la conexión a la base de datos «%s»" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"no se pudo establecer la conexión a las bases de datos «postgres» o\n" +"«template1». Por favor especifique una base de datos para conectarse." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s extrae un cluster de bases de datos de PostgreSQL en un archivo\n" +"guión (script) SQL.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [OPCIÓN]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=ARCHIVO nombre del archivo de salida\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean tira (drop) la base de datos antes de crearla\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only extrae sólo los objetos globales, no bases de datos\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner no reestablece los dueños de los objetos\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only extrae sólo los roles, no bases de datos\n" +" ni tablespaces\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr "" +" -S, --superuser=NAME especifica el nombre del superusuario a usar en\n" +" el volcado\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only extrae sólo los tablespaces, no bases de datos\n" +" ni roles\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=PATRÓN excluir bases de datos cuyos nombres coinciden con el patrón\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords no extraer contraseñas para roles\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR conectar usando la cadena de conexión\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=NOMBRE especifica la base de datos a la cual conectarse\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Si no se usa -f/--file, el volcado de SQL será escrito a la salida estándar.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "omitido nombre de rol que empieza con «pg_» (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "no se pudo interpretar la lista de control de acceso (%s) del tablespace «%s»" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "excluyendo base de datos «%s»" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "extrayendo base de datos «%s»" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump falló en la base de datos «%s», saliendo" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "no se pudo reabrir el archivo de salida «%s»: %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "ejecutando «%s»" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "no se pudo obtener la versión del servidor" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "no se pudo interpretar la versión del servidor «%s»" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "ejecutando %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "una de las opciones -d/--dbname y -f/--file debe especificarse" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "las opciones -d/--dbname y -f/--file no pueden usarse juntas" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "las opciones -c/--clean y -1/--single-transaction no pueden usarse juntas" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "el número máximo de trabajos en paralelo es %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "no se puede especificar --single-transaction junto con múltiples tareas" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "formato de archivo «%s» no reconocido; por favor especifique «c», «d» o «t»" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "errores ignorados durante la recuperación: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s reestablece una base de datos de PostgreSQL usando un archivo\n" +"creado por pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [OPCIÓN]... [ARCHIVO]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NOMBRE nombre de la base de datos a la que conectarse\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=ARCHIVO nombre del archivo de salida (- para stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t formato del volcado (debería ser automático)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr "" +" -l, --list imprime una tabla resumida de contenidos\n" +" del archivador\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose modo verboso\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de versión y salir\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda y salir\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Opciones que controlan la recuperación:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only reestablece sólo los datos, no el esquema\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create crea la base de datos de destino\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr "" +" -e, --exit-on-error abandonar al encontrar un error\n" +" por omisión, se continúa la restauración\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NOMBRE reestablece el índice nombrado\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM máximo de procesos paralelos para restaurar\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=ARCHIVO usa la tabla de contenido especificada para ordenar\n" +" la salida de este archivo\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME reestablece sólo los objetos en este esquema\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME no reestablecer los objetos en este esquema\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NOMBRE(args) reestablece la función nombrada\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only reestablece el esquema únicamente, no los datos\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr "" +" -S, --superuser=NOMBRE especifica el nombre del superusuario que se usa\n" +" para deshabilitar los disparadores (triggers)\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NOMBRE reestablece la relación (tabla, vista, etc.) nombrada\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NOMBRE reestablece el disparador (trigger) nombrado\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges no reestablece los privilegios (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction reestablece en una única transacción\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security activa seguridad de filas\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments no restaurar comentarios\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables no reestablece datos de tablas que no pudieron\n" +" ser creadas\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications no restaurar publicaciones\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels no restaura etiquetas de seguridad\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions no restaurar suscripciones\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces no vuelca asignaciones de tablespace\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECCIÓN reestablece la sección nombrada (pre-data, data\n" +" post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME hace SET ROLE antes de restaurar\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Las opciones -I, -n, -N, -P, -t, -T, y --section pueden ser combinadas y especificadas\n" +"varias veces para seleccionar varios objetos.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Si no se especifica un archivo de entrada, se usa la entrada estándar.\n" +"\n" diff --git a/src/bin/pg_dump/po/fr.po b/src/bin/pg_dump/po/fr.po new file mode 100644 index 0000000..02bd2f6 --- /dev/null +++ b/src/bin/pg_dump/po/fr.po @@ -0,0 +1,3345 @@ +# translation of pg_dump.po to fr_fr +# french message translation file for pg_dump +# +# Use these quotes: « %s » +# +# Guillaume Lelarge , 2004-2009. +# Stéphane Schildknecht , 2009. +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 12\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-05-03 03:04+0000\n" +"PO-Revision-Date: 2021-12-30 17:13+0100\n" +"Last-Translator: Guillaume Lelarge \n" +"Language-Team: PostgreSQLfr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.0.1\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "fatal : " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "erreur : " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "attention : " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "n'a pas pu identifier le répertoire courant : %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "binaire « %s » invalide" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "n'a pas pu lire le binaire « %s »" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "n'a pas pu trouver un « %s » à exécuter" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "n'a pas pu modifier le répertoire par « %s » : %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "n'a pas pu lire le lien symbolique « %s » : %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "échec de %s() : %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "mémoire épuisée" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "commande non exécutable" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "commande introuvable" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "le processus fils a quitté avec le code de sortie %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "le processus fils a été terminé par l'exception 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "le processus fils a été terminé par le signal %d : %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "le processus fils a quitté avec un statut %d non reconnu" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "lecture des extensions" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "identification des membres d'extension" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "lecture des schémas" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "lecture des tables utilisateur" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "lecture des fonctions utilisateur" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "lecture des types utilisateur" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "lecture des langages procéduraux" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "lecture des fonctions d'agrégats utilisateur" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "lecture des opérateurs utilisateur" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "lecture des méthodes d'accès définis par les utilisateurs" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "lecture des classes d'opérateurs utilisateur" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "lecture des familles d'opérateurs utilisateur" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "lecture des analyseurs utilisateur pour la recherche plein texte" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "lecture des modèles utilisateur pour la recherche plein texte" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "lecture des dictionnaires utilisateur pour la recherche plein texte" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "lecture des configurations utilisateur pour la recherche plein texte" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "lecture des wrappers de données distantes utilisateur" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "lecture des serveurs distants utilisateur" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "lecture des droits par défaut" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "lecture des collationnements utilisateurs" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "lecture des conversions utilisateur" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "lecture des conversions de type" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "lecture des transformations" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "lecture des informations d'héritage des tables" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "lecture des triggers sur évènement" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "recherche des tables d'extension" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "recherche des relations d'héritage" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "lecture des informations de colonnes des tables intéressantes" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "marquage des colonnes héritées dans les sous-tables" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "lecture des index" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "décrit les index des tables partitionnées" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "lecture des statistiques étendues" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "lecture des contraintes" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "lecture des triggers" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "lecture des règles de réécriture" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "lecture des politiques" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "lecture des publications" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "lecture des appartenances aux publications" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "lecture des souscriptions" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "nombre de parents invalide (%d) pour la table « %s »" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "vérification échouée, OID %u parent de la table « %s » (OID %u) introuvable" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "n'a pas pu analyser le tableau numérique « %s » : trop de nombres" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "n'a pas pu analyser le tableau numérique « %s » : caractère invalide dans le nombre" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "code de compression invalide : %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "pas construit avec le support de zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "n'a pas pu initialiser la bibliothèque de compression : %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "n'a pas pu fermer le flux de compression : %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "n'a pas pu compresser les données : %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "n'a pas pu décompresser les données : %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "n'a pas pu fermer la bibliothèque de compression : %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "n'a pas pu lire à partir du fichier en entrée : %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "n'a pas pu lire à partir du fichier en entrée : fin du fichier" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "échec de %s() : code d'erreur %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "n'a pas pu créer le canal de communication : %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "n'a pas pu créer le processus worker : %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "commande non reconnue reçue du leader : « %s »" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "message invalide reçu du worker: « %s »" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"impossible d'obtenir un verrou sur la relation « %s »\n" +"Cela signifie en général que quelqu'un a demandé un verrou ACCESS EXCLUSIVE sur la table après que pg_dump ait obtenu son verrou ACCESS SHARE initial sur la table." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "un processus worker a subi un arrêt brutal inattendu" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "n'a pas pu écrire dans le canal de communication: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: n'a pas pu créer le socket: code d'erreur %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: n'a pas pu se lier: code d'erreur %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe : n'a pas pu se mettre en écoute: code d'erreur %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: échec de %s() : code d'erreur %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: n'a pas pu créer un deuxième socket: code d'erreur %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: n'a pas pu se connecter au socket: code d'erreur %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: n'a pas pu accepter de connexion: code d'erreur %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "n'a pas pu fermer le fichier en sortie : %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "les éléments de l'archive ne sont pas dans l'ordre correct de la section" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "code de section inattendu %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "la restauration parallélisée n'est pas supportée avec ce format de fichier d'archive" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "la restauration parallélisée n'est pas supportée avec les archives réalisées par un pg_dump antérieur à la 8.0" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "ne peut pas restaurer à partir de l'archive compressée (compression indisponible dans cette installation)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "connexion à la base de données pour la restauration" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "les connexions directes à la base de données ne sont pas supportées dans les archives pre-1.3" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "a impliqué une restauration des données uniquement" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "suppression de %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "n'a pas pu trouver où insérer IF EXISTS dans l'instruction « %s »" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "message d'avertissement du fichier de sauvegarde original : %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "création de %s « %s.%s »" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "création de %s « %s »" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "connexion à la nouvelle base de données « %s »" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "traitement de %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "traitement des données de la table « %s.%s »" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "exécution de %s %s" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "désactivation des triggers pour %s" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "activation des triggers pour %s" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "erreur interne -- WriteData ne peut pas être appelé en dehors du contexte de la routine DataDumper" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "la sauvegarde des « Large Objects » n'est pas supportée dans le format choisi" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "restauration de %d « Large Object »" +msgstr[1] "restauration de %d « Large Objects »" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "restauration du « Large Object » d'OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "n'a pas pu créer le « Large Object » %u : %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "n'a pas pu ouvrir le « Large Object » %u : %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier TOC « %s » : %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "ligne ignorée : %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "n'a pas pu trouver l'entrée pour l'ID %d" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "n'a pas pu fermer le fichier TOC : %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier de sauvegarde « %s » : %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "n'a pas pu ouvrir le fichier de sauvegarde : %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "a écrit %zu octet de données d'un « Large Object » (résultat = %d)" +msgstr[1] "a écrit %zu octets de données d'un « Large Object » (résultat = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "n'a pas pu écrire dans le « Large Object » : %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "pendant l'initialisation (« INITIALIZING ») :" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "pendant le traitement de la TOC (« PROCESSING TOC ») :" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "pendant la finalisation (« FINALIZING ») :" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "de l'entrée TOC %d ; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "mauvais dumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "mauvais dumpId de table pour l'élément TABLE DATA" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "drapeau de décalage de données inattendu %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "le décalage dans le fichier de sauvegarde est trop important" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "nom du répertoire trop long : « %s »" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "le répertoire « %s » ne semble pas être une archive valide (« toc.dat » n'existe pas)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier en entrée « %s » : %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "n'a pas pu ouvrir le fichier en entrée : %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "n'a pas pu lire le fichier en entrée : %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "le fichier en entrée est trop petit (%lu lus, 5 attendus)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "Le fichier en entrée semble être une sauvegarde au format texte. Merci d'utiliser psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "le fichier en entrée ne semble pas être une archive valide (trop petit ?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "le fichier en entrée ne semble pas être une archive valide" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "n'a pas pu fermer le fichier en entrée : %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "format de fichier « %d » non reconnu" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "élément terminé %d %s %s" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "échec du processus worker : code de sortie %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "ID %d de l'entrée en dehors de la plage -- peut-être un TOC corrompu" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "la restauration des tables avec WITH OIDS n'est plus supportée" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "encodage « %s » non reconnu" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "élément ENCODING invalide : %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "élément STDSTRINGS invalide : %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "schéma « %s » non trouvé" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "table « %s » non trouvée" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "index « %s » non trouvé" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "fonction « %s » non trouvée" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "trigger « %s » non trouvé" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "n'a pas pu initialiser la session utilisateur à « %s »: %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "n'a pas pu configurer search_path à « %s » : %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "n'a pas pu configurer default_tablespace à %s : %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "n'a pas pu configurer la méthode default_table_access_method à %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "ne sait pas comment initialiser le propriétaire du type d'objet « %s »" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "n'a pas trouver la chaîne magique dans le fichier d'en-tête" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "version non supportée (%d.%d) dans le fichier d'en-tête" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "échec de la vérification sur la taille de l'entier (%lu)" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "l'archive a été créée sur une machine disposant d'entiers plus larges, certaines opérations peuvent échouer" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "le format attendu (%d) diffère du format du fichier (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "l'archive est compressée mais cette installation ne supporte pas la compression -- aucune donnée ne sera disponible" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "date de création invalide dans l'en-tête" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "traitement de l'élément %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "entrée dans la boucle parallèle principale" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "omission de l'élément %d %s %s" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "lancement de l'élément %d %s %s" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "fin de la boucle parallèle principale" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "traitement de l'élément manquant %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "la table « %s » n'a pas pu être créée, ses données ne seront pas restaurées" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "OID invalide pour le « Large Object »" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "erreur lors de la recherche dans le fichier : %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "le bloc de données %d a une mauvaise position de recherche" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "type de bloc de données non reconnu (%d) lors de la recherche dans l'archive" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "" +"n'a pas pu trouver l'identifiant de bloc %d dans l'archive --\n" +"il est possible que cela soit dû à une demande de restauration dans un ordre\n" +"différent, ce qui ne peut pas être géré à cause d'un fichier non gérable en\n" +"recherche" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "n'a pas pu trouver l'identifiant de bloc %d dans l'archive -- possible corruption de l'archive" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "ID de bloc inattendu (%d) lors de la lecture des données -- %d attendu" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "type de bloc de données %d non reconnu lors de la restauration de l'archive" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "n'a pas pu lire à partir du fichier en entrée : %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "n'a pas pu déterminer la position de recherche dans le fichier d'archive : %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "n'a pas pu fermer le fichier d'archive : %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "peut seulement rouvrir l'archive en entrée" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "la restauration parallélisée n'est pas supportée à partir de stdin" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "la restauration parallélisée n'est pas supportée à partir de fichiers sans table de matière" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "n'a pas pu initialiser la recherche de position dans le fichier d'archive : %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "compression activée" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "n'a pas pu obtenir server_version de libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "version du serveur : %s ; %s version : %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "annulation à cause de la différence des versions" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "déjà connecté à une base de données" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Mot de passe : " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "n'a pas pu se connecter à la base de données" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "échec de la reconnexion : %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "échec de la requête : %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "la requête était : %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "la requête a renvoyé %d ligne au lieu d'une seule : %s" +msgstr[1] "la requête a renvoyé %d lignes au lieu d'une seule : %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sLa commande était : %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "n'a pas pu exécuter la requête" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "erreur renvoyée par PQputCopyData : %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "erreur renvoyée par PQputCopyEnd : %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY échoué pour la table « %s » : %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "résultats supplémentaires non attendus durant l'exécution de COPY sur la table « %s »" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "n'a pas pu démarrer la transaction de la base de données" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "n'a pas pu valider la transaction de la base de données" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "aucun répertoire cible indiqué" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "n'a pas pu fermer le répertoire « %s » : %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "n'a pas pu créer le répertoire « %s » : %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "n'a pas pu écrire dans le fichier en sortie : %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "n'a pas pu fermer le fichier de données : %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier de données « %s » : %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "n'a pas pu ouvrir le fichier TOC « %s » du Large Object en entrée : %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "ligne invalide dans le fichier TOC du Large Object « %s » : « %s »" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "erreur lors de la lecture du TOC du fichier Large Object « %s »" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "n'a pas pu fermer le TOC du Large Object « %s » : %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "n'a pas pu fermer le fichier de données blob : %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "n'a pas pu écrire dans le fichier TOC des Large Objects" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "n'a pas pu fermer le fichier TOC des blobs : %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "nom du fichier trop long : « %s »" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "ce format ne peut pas être lu" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "n'a pas pu ouvrir le fichier TOC « %s » en sortie : %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "n'a pas pu ouvrir le fichier TOC en sortie : %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "compression non supportée par le format des archives tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "n'a pas pu ouvrir le fichier TOC « %s » en entrée : %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "n'a pas pu ouvrir le fichier TOC en entrée : %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "n'a pas pu trouver le fichier « %s » dans l'archive" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "impossible de créer le nom du fichier temporaire : %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "n'a pas pu ouvrir le fichier temporaire" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "n'a pas pu fermer le membre de tar : %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "syntaxe inattendue de l'instruction COPY : « %s »" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "OID invalide pour le « Large Object » (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "n'a pas pu fermer le fichier temporaire : m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "la longueur réelle du fichier (%s) ne correspond pas à ce qui était attendu (%s)" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "n'a pas pu trouver l'en-tête du fichier « %s » dans l'archive tar" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "la restauration désordonnée de données n'est pas supportée avec ce format d'archive : « %s » est requis mais vient avant « %s » dans le fichier d'archive." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "en-tête incomplet du fichier tar (%lu octet)" +msgstr[1] "en-tête incomplet du fichier tar (%lu octets)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "en-tête tar corrompu trouvé dans %s (%d attendu, %d calculé ) à la position %s du fichier" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "nom de section non reconnu : « %s »" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Essayer « %s --help » pour plus d'informations.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "plus d'emplacements on_exit_nicely" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "le niveau de compression doit être compris entre 0 et 9" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits doit être dans l'intervalle -15 à 3" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "le nombre de lignes par insertion doit être compris entre %d et %d" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "les options « -s/--schema-only » et « -a/--data-only » ne peuvent pas être utilisées ensemble" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "les options « -s/--schema-only » et « --include-foreign-data » ne peuvent pas être utilisées ensemble" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "l'option --include-foreign-data n'est pas supportée avec une sauvegarde parallélisée" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "les options « -c/--clean » et « -a/--data-only » ne peuvent pas être utilisées ensemble" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "l'option --if-exists nécessite l'option -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "l'option --on-conflict-do-nothing requiert l'option --inserts, --rows-per-insert, ou --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "la compression requise n'est pas disponible avec cette installation -- l'archive ne sera pas compressée" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "nombre de jobs parallèles invalide" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "la sauvegarde parallélisée n'est supportée qu'avec le format directory" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Les snapshots synchronisés ne sont pas supportés par cette version serveur.\n" +"Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" +"de snapshots synchronisés." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Les images exportées de la base ne sont pas supportées par cette version du serveur." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "le dernier OID interne est %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "aucun schéma correspondant n'a été trouvé" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "aucune table correspondante n'a été trouvée" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "aucune extension correspondante n'a été trouvée" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s exporte une base de données dans un fichier texte ou dans d'autres\n" +"formats.\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Usage :\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [OPTION]... [BASE]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Options générales :\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=FICHIER nom du fichier ou du répertoire en sortie\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p format du fichier de sortie (personnalisé,\n" +" répertoire, tar, texte (par défaut))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr "" +" -j, --jobs=NOMBRE utilise ce nombre de jobs en parallèle pour la\n" +" sauvegarde\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose mode verbeux\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr "" +" -Z, --compress=0-9 niveau de compression pour les formats\n" +" compressés\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr "" +" --lock-wait-timeout=DÉLAI échec après l'attente du DÉLAI pour un verrou de\n" +" table\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr "" +" --no-sync n'attend pas que les modifications soient\n" +" proprement écrites sur disque\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Options contrôlant le contenu en sortie :\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only sauvegarde uniquement les données, pas le schéma\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs inclut les « Large Objects » dans la sauvegarde\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs exclut les « Large Objects » de la sauvegarde\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr "" +" -c, --clean nettoie/supprime les objets de la base de données\n" +" avant de les créer\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr "" +" -C, --create inclut les commandes de création de la base\n" +" dans la sauvegarde\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=MOTIF sauvegarde uniquement les extensions indiquées\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=ENCODAGE sauvegarde les données dans l'encodage ENCODAGE\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=MOTIF sauvegarde uniquement les schémas indiqués\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=MOTIF ne sauvegarde pas les schémas indiqués\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner ne sauvegarde pas les propriétaires des objets\n" +" lors de l'utilisation du format texte\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr "" +" -s, --schema-only sauvegarde uniquement la structure, pas les\n" +" données\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr "" +" -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" +" avec le format texte\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=MOTIF sauvegarde uniquement les tables indiquées\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=MOTIF ne sauvegarde pas les tables indiquées\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges ne sauvegarde pas les droits sur les objets\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr "" +" --binary-upgrade à n'utiliser que par les outils de mise à jour\n" +" seulement\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr "" +" --column-inserts sauvegarde les données avec des commandes INSERT\n" +" en précisant les noms des colonnes\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr "" +" --disable-dollar-quoting désactive l'utilisation des guillemets dollars\n" +" dans le but de respecter le standard SQL en\n" +" matière de guillemets\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr "" +" --disable-triggers désactive les triggers en mode de restauration\n" +" des données seules\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security active la sécurité niveau ligne (et donc\n" +" sauvegarde uniquement le contenu visible par cet\n" +" utilisateur)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=MOTIF ne sauvegarde pas les tables indiquées\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr "" +" --extra-float-digits=NUM surcharge la configuration par défaut de\n" +" extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr "" +" --if-exists utilise IF EXISTS lors de la suppression des\n" +" objets\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=MOTIF inclut les données des tables externes pour les\n" +" serveurs distants correspondant au motif MOTIF\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr "" +" --inserts sauvegarde les données avec des instructions\n" +" INSERT plutôt que COPY\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root charger les partitions via la table racine\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments ne sauvegarde pas les commentaires\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications ne sauvegarde pas les publications\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr "" +" --no-security-labels ne sauvegarde pas les affectations de labels de\n" +" sécurité\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions ne sauvegarde pas les souscriptions\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr "" +" --no-synchronized-snapshots n'utilise pas de snapshots synchronisés pour les\n" +" jobs en parallèle\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces ne sauvegarde pas les affectations de tablespaces\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr "" +" --no-toast-compression ne sauvegarde pas les méthodes de compression de\n" +" TOAST\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr "" +" --no-unlogged-table-data ne sauvegarde pas les données des tables non\n" +" journalisées\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr "" +" --on-conflict-do-nothing ajoute ON CONFLICT DO NOTHING aux commandes\n" +" INSERT\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers met entre guillemets tous les identifiants même\n" +" s'il ne s'agit pas de mots clés\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS nombre de lignes par INSERT ; implique --inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECTION sauvegarde la section indiquée (pre-data, data\n" +" ou post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr "" +" --serializable-deferrable attend jusqu'à ce que la sauvegarde puisse\n" +" s'exécuter sans anomalies\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT utilise l'image donnée pour la sauvegarde\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names requiert que les motifs des tables et/ou schémas\n" +" correspondent à au moins une entité de chaque\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" utilise les commandes SET SESSION AUTHORIZATION\n" +" au lieu des commandes ALTER OWNER pour modifier\n" +" les propriétaires\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Options de connexion :\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=BASE base de données à sauvegarder\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr "" +" -h, --host=HÔTE hôte du serveur de bases de données ou\n" +" répertoire des sockets\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT numéro de port du serveur de bases de données\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NOM se connecter avec cet utilisateur\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password ne demande jamais un mot de passe\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr "" +" -W, --password force la demande du mot de passe (devrait\n" +" survenir automatiquement)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=NOMROLE exécute SET ROLE avant la sauvegarde\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Si aucune base de données n'est indiquée, la valeur de la variable\n" +"d'environnement PGDATABASE est alors utilisée.\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Rapporter les bogues à <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Page d'accueil de %s : <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "encodage client indiqué (« %s ») invalide" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Les snapshots synchronisés sur les serveurs standbys ne sont pas supportés par cette version serveur.\n" +"Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" +"de snapshots synchronisés." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "format de sortie « %s » invalide" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "aucun schéma correspondant n'a été trouvé avec le motif « %s »" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "aucune extension correspondante n'a été trouvée avec le motif « %s »" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "aucun serveur distant correspondant n'a été trouvé avec le motif « %s »" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "nom de relation incorrecte (trop de points entre les noms) : %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "aucune table correspondante n'a été trouvée avec le motif « %s »" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "Vous n'êtes pas connecté à une base de données." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "les références entre bases de données ne sont pas implémentées : %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "sauvegarde du contenu de la table « %s.%s »" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Sauvegarde du contenu de la table « %s » échouée : échec de PQgetCopyData()." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Message d'erreur du serveur : %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "La commande était : %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Sauvegarde du contenu de la table « %s » échouée : échec de PQgetResult()." + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "mauvais nombre de champs récupérés à partir de la table « %s »" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "sauvegarde de la définition de la base de données" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "encodage de la sauvegarde = %s" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "sauvegarde de standard_conforming_strings = %s" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "n'a pas pu analyser le résultat de current_schema()" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "sauvegarde de search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "lecture des « Large Objects »" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "sauvegarde des « Large Objects »" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "erreur lors de la lecture du « Large Object » %u : %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "lecture des politiques de sécurité au niveau ligne" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "type de commande inattendu pour la politique : %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "le propriétaire de la publication « %s » semble être invalide" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "les souscriptions ne sont pas sauvegardées parce que l'utilisateur courant n'est pas un superutilisateur" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "le propriétaire de la souscription « %s » semble être invalide" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "n'a pas pu analyser le tableau de sous-publications" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "n'a pas pu trouver l'extension parent pour %s %s" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "le propriétaire du schéma « %s » semble être invalide" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "le schéma d'OID %u n'existe pas" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "le propriétaire du type de données « %s » semble être invalide" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "le propriétaire de l'opérateur « %s » semble être invalide" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "le propriétaire de la classe d'opérateur « %s » semble être invalide" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "le propriétaire de la famille d'opérateur « %s » semble être invalide" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "le propriétaire de la fonction d'agrégat « %s » semble être invalide" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "le propriétaire de la fonction « %s » semble être invalide" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "le propriétaire de la table « %s » semble être invalide" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "vérification échouée, OID %u de la table parent de l'OID %u de la séquence introuvable" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "lecture des index de la table « %s.%s »" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "lecture des contraintes de clés étrangères pour la table « %s.%s »" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "vérification échouée, OID %u de la table parent de l'OID %u de l'entrée de pg_rewrite introuvable" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "lecture des triggers pour la table « %s.%s »" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "la requête a produit une réference de nom de table null pour le trigger de la clé étrangère « %s » sur la table « %s » (OID de la table : %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "recherche des colonnes et types de la table « %s.%s »" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "numérotation des colonnes invalide pour la table « %s »" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "recherche des expressions par défaut de la table « %s.%s »" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "valeur adnum %d invalide pour la table « %s »" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "recherche des contraintes de vérification pour la table « %s.%s »" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "%d contrainte de vérification attendue pour la table « %s » mais %d trouvée" +msgstr[1] "%d contraintes de vérification attendues pour la table « %s » mais %d trouvée" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Les catalogues système sont peut-être corrompus.)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "la colonne typtype du type de données « %s » semble être invalide" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "valeur erronée dans le tableau proargmodes" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "n'a pas pu analyser le tableau proallargtypes" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "n'a pas pu analyser le tableau proargmodes" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "n'a pas pu analyser le tableau proargnames" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "n'a pas pu analyser le tableau proconfig" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "valeur provolatile non reconnue pour la fonction « %s »" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "valeur proparallel non reconnue pour la fonction « %s »" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "n'a pas pu trouver la définition de la fonction d'OID %u" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "valeur erronée dans le champ pg_cast.castfunc ou pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "valeur erronée dans pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "définition de transformation invalide, au moins un de trffromsql et trftosql ne doit pas valoir 0" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "valeur erronée dans pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "valeur erronée dans pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "les opérateurs postfixes ne sont plus supportés (opérateur « %s »)" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "n'a pas pu trouver l'opérateur d'OID %s" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "type « %c » invalide de la méthode d'accès « %s »" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "fournisseur de collationnement non reconnu : %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "valeur non reconnue de aggfinalmodify pour l'agrégat « %s »" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "valeur non reconnue de aggmfinalmodify pour l'agrégat « %s »" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "type d'objet inconnu dans les droits par défaut : %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "n'a pas pu analyser la liste ACL par défaut (%s)" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "n'a pas pu analyser la liste ACL GRANT initiale (%s) ou la liste ACL REVOKE initiale (%s) de l'objet « %s » (%s)" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "n'a pas pu analyser la liste ACL GRANT (%s) ou REVOKE (%s) de l'objet « %s » (%s)" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "la requête permettant d'obtenir la définition de la vue « %s » n'a renvoyé aucune donnée" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "la requête permettant d'obtenir la définition de la vue « %s » a renvoyé plusieurs définitions" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "la définition de la vue « %s » semble être vide (longueur nulle)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS n'est plus supporté (table « %s »)" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "numéro de colonne %d invalide pour la table « %s »" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "n'a pas pu analyser les colonnes statistiques de l'index" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "n'a pas pu analyser les valeurs statistiques de l'index" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "nombre de colonnes et de valeurs différentes pour les statistiques des index" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "index manquant pour la contrainte « %s »" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "type de contrainte inconnu : %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé %d ligne (une seule attendue)" +msgstr[1] "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé %d ligne (une seule attendue)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "type de séquence non reconnu : « %s »" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "valeur tgtype inattendue : %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "chaîne argument invalide (%s) pour le trigger « %s » sur la table « %s »" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "la requête permettant d'obtenir la règle « %s » associée à la table « %s » a échoué : mauvais nombre de lignes renvoyées" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "n'a pas pu trouver l'extension référencée %u" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "n'a pas pu analyser le tableau de configuration des extensions" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "n'a pas pu analyser le tableau de condition de l'extension" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "nombre différent de configurations et de conditions pour l'extension" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "lecture des données de dépendance" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "pas d'objet référant %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "pas d'objet référencé %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "n'a pas pu analyser le tableau reloptions" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "dumpId %d invalide" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "dépendance invalide %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "n'a pas pu identifier la boucle de dépendance" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "NOTE : il existe des constraintes de clés étrangères circulaires sur cette table :" +msgstr[1] "NOTE : il existe des constraintes de clés étrangères circulaires sur ces tables :" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Il est possible de restaurer la sauvegarde sans utiliser --disable-triggers ou sans supprimer temporairement les constraintes." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Considérez l'utilisation d'une sauvegarde complète au lieu d'une sauvegarde des données seulement pour éviter ce problème." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "n'a pas pu résoudre la boucle de dépendances parmi ces éléments :" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé\n" +"dans le même répertoire que « %s ».\n" +"Vérifiez votre installation." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Le programme « %s » a été trouvé par « %s »\n" +"mais n'est pas de la même version que %s.\n" +"Vérifiez votre installation." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "l'option --exclude-database ne peut pas être utilisée avec -g/--globals-only, -r/--roles-only ou -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "les options « -g/--globals-only » et « -r/--roles-only » ne peuvent pas être utilisées ensemble" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "les options « -g/--globals-only » et « -t/--tablespaces-only » ne peuvent pas être utilisées ensemble" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "les options « -r/--roles-only » et « -t/--tablespaces-only » ne peuvent pas être utilisées ensemble" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "n'a pas pu se connecter à la base de données « %s »" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"n'a pas pu se connecter aux bases « postgres » et « template1 ».\n" +"Merci de préciser une autre base de données." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s extrait un cluster de bases de données PostgreSQL dans un fichier de\n" +"commandes SQL.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [OPTION]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=FICHIER nom du fichier de sortie\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr "" +" -c, --clean nettoie (supprime) les bases de données avant de\n" +" les créer\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr "" +" -g, --globals-only sauvegarde uniquement les objets système, pas\n" +" le contenu des bases de données\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner omet la restauration des propriétaires des objets\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only sauvegarde uniquement les rôles, pas les bases\n" +" de données ni les tablespaces\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr "" +" -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" +" avec le format texte\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only sauvegarde uniquement les tablespaces, pas les\n" +" bases de données ni les rôles\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr "" +" --exclude-database=MOTIF exclut les bases de données dont le nom\n" +" correspond au motif\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords ne sauvegarde pas les mots de passe des rôles\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CHAINE_CONNEX connexion à l'aide de la chaîne de connexion\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=BASE indique une autre base par défaut\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Si -f/--file n'est pas utilisé, le script SQL sera envoyé sur la sortie\n" +"standard.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "nom de rôle commençant par « pg_ » ignoré (« %s »)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "n'a pas pu analyser la liste d'ACL (%s) pour le tablespace « %s »" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "exclusion de la base de données « %s »" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "sauvegarde de la base de données « %s »" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "échec de pg_dump sur la base de données « %s », quitte" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "n'a pas pu ré-ouvrir le fichier de sortie « %s » : %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "exécute « %s »" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "n'a pas pu obtenir la version du serveur" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "n'a pas pu analyser la version du serveur « %s »" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "exécution %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "une seule des options -d/--dbname and -f/--file peut être indiquée" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "les options « -d/--dbname » et « -f/--file » ne peuvent pas être utilisées ensemble" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "les options « -c/--clean » et « -a/--data-only » ne peuvent pas être utilisées ensemble" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "le nombre maximum de jobs en parallèle est %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "ne peut pas spécifier à la fois l'option --single-transaction et demander plusieurs jobs" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "format d'archive « %s » non reconnu ; merci d'indiquer « c », « d » ou « t »" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "erreurs ignorées lors de la restauration : %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s restaure une base de données PostgreSQL à partir d'une archive créée\n" +"par pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [OPTION]... [FICHIER]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr "" +" -d, --dbname=NOM nom de la base de données utilisée pour la\n" +" connexion\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FICHIER nom du fichier de sortie (- pour stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr "" +" -F, --format=c|d|t format du fichier de sauvegarde (devrait être\n" +" automatique)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list affiche la table des matières de l'archive (TOC)\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose mode verbeux\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Options contrôlant la restauration :\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only restaure uniquement les données, pas la structure\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create crée la base de données cible\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error quitte en cas d'erreur, continue par défaut\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NOM restaure l'index indiqué\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr "" +" -j, --jobs=NOMBRE utilise ce nombre de jobs en parallèle pour la\n" +" restauration\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FICHIER utilise la table des matières à partir de ce\n" +" fichier pour sélectionner/trier la sortie\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NOM restaure uniquement les objets de ce schéma\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NOM ne restaure pas les objets de ce schéma\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NOM(args) restaure la fonction indiquée\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only restaure uniquement la structure, pas les données\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr "" +" -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" +" pour désactiver les triggers\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NOM restaure la relation indiquée (table, vue, etc)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NOM restaure le trigger indiqué\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr "" +" -x, --no-privileges omet la restauration des droits sur les objets\n" +" (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction restaure dans une seule transaction\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security active la sécurité niveau ligne\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments ne restaure pas les commentaires\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables ne restaure pas les données des tables qui n'ont\n" +" pas pu être créées\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications ne restaure pas les publications\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels ne restaure pas les labels de sécurité\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions ne restaure pas les souscriptions\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces ne restaure pas les affectations de tablespaces\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECTION restaure la section indiquée (pre-data, data ou\n" +" post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=RÔLE exécute SET ROLE avant la restauration\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Les options -I, -n, -N, -P, -t, -T et --section peuvent être combinées et\n" +"indiquées plusieurs fois pour sélectionner plusieurs objets.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Si aucun nom de fichier n'est fourni en entrée, alors l'entrée standard est\n" +"utilisée.\n" +"\n" + +#~ msgid " --disable-triggers disable triggers during data-only restore\n" +#~ msgstr "" +#~ " --disable-triggers désactiver les déclencheurs lors de la\n" +#~ " restauration des données seules\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help affiche cette aide puis quitte\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help affiche cette aide et quitte\n" + +#~ msgid "" +#~ " --use-set-session-authorization\n" +#~ " use SET SESSION AUTHORIZATION commands instead of\n" +#~ " ALTER OWNER commands to set ownership\n" +#~ msgstr "" +#~ " --use-set-session-authorization\n" +#~ " utilise les commandes SET SESSION AUTHORIZATION\n" +#~ " au lieu des commandes ALTER OWNER pour les\n" +#~ " modifier les propriétaires\n" + +#~ msgid " --version output version information, then exit\n" +#~ msgstr " --version affiche la version puis quitte\n" + +#~ msgid " --version output version information, then exit\n" +#~ msgstr " --version affiche la version et quitte\n" + +#~ msgid " -O, --no-owner skip restoration of object ownership\n" +#~ msgstr "" +#~ " -O, --no-owner omettre la restauration des possessions des\n" +#~ " objets\n" + +#~ msgid " -c, --clean clean (drop) database objects before recreating\n" +#~ msgstr "" +#~ " -c, --clean nettoie/supprime les bases de données avant de\n" +#~ " les créer\n" + +#~ msgid " -o, --oids include OIDs in dump\n" +#~ msgstr " -o, --oids inclut les OID dans la sauvegarde\n" + +#~ msgid "%s: could not connect to database \"%s\": %s" +#~ msgstr "%s : n'a pas pu se connecter à la base de données « %s » : %s" + +#~ msgid "%s: could not open the output file \"%s\": %s\n" +#~ msgstr "%s : n'a pas pu ouvrir le fichier de sauvegarde « %s » : %s\n" + +#~ msgid "%s: could not parse ACL list (%s) for database \"%s\"\n" +#~ msgstr "%s : n'a pas pu analyser la liste d'ACL (%s) pour la base de données « %s »\n" + +#~ msgid "%s: could not parse version \"%s\"\n" +#~ msgstr "%s : n'a pas pu analyser la version « %s »\n" + +#~ msgid "%s: executing %s\n" +#~ msgstr "%s : exécute %s\n" + +#~ msgid "%s: invalid -X option -- %s\n" +#~ msgstr "%s : option -X invalide -- %s\n" + +#~ msgid "%s: invalid client encoding \"%s\" specified\n" +#~ msgstr "%s : encodage client indiqué (« %s ») invalide\n" + +#~ msgid "%s: invalid number of parallel jobs\n" +#~ msgstr "%s : nombre de jobs en parallèle invalide\n" + +#~ msgid "%s: option --if-exists requires option -c/--clean\n" +#~ msgstr "%s : l'option --if-exists nécessite l'option -c/--clean\n" + +#~ msgid "%s: options -c/--clean and -a/--data-only cannot be used together\n" +#~ msgstr "" +#~ "%s : les options « -c/--clean » et « -a/--data-only » ne peuvent pas être\n" +#~ "utilisées conjointement\n" + +#~ msgid "%s: options -s/--schema-only and -a/--data-only cannot be used together\n" +#~ msgstr "" +#~ "%s : les options « -s/--schema-only » et « -a/--data-only » ne peuvent pas être\n" +#~ "utilisées conjointement\n" + +#~ msgid "%s: out of memory\n" +#~ msgstr "%s : mémoire épuisée\n" + +#~ msgid "%s: query failed: %s" +#~ msgstr "%s : échec de la requête : %s" + +#~ msgid "%s: query was: %s\n" +#~ msgstr "%s : la requête était : %s\n" + +#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" +#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" + +#~ msgid "(The INSERT command cannot set OIDs.)\n" +#~ msgstr "(La commande INSERT ne peut pas positionner les OID.)\n" + +#~ msgid "*** aborted because of error\n" +#~ msgstr "*** interrompu du fait d'erreurs\n" + +#~ msgid "-C and -1 are incompatible options\n" +#~ msgstr "-C et -1 sont des options incompatibles\n" + +#~ msgid "-C and -c are incompatible options\n" +#~ msgstr "-C et -c sont des options incompatibles\n" + +#~ msgid "LOCK TABLE failed for \"%s\": %s" +#~ msgstr "LOCK TABLE échoué pour la table « %s » : %s" + +#~ msgid "Report bugs to .\n" +#~ msgstr "Rapporter les bogues à .\n" + +#~ msgid "Report bugs to .\n" +#~ msgstr "Rapporter les bogues à .\n" + +#~ msgid "SQL command failed\n" +#~ msgstr "la commande SQL a échoué\n" + +#~ msgid "" +#~ "Synchronized snapshots are not supported on standby servers.\n" +#~ "Run with --no-synchronized-snapshots instead if you do not need\n" +#~ "synchronized snapshots.\n" +#~ msgstr "" +#~ "Les snapshots synchronisés ne sont pas supportés sur les serveurs de stadby.\n" +#~ "Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" +#~ "de snapshots synchronisés.\n" + +#~ msgid "TOC Entry %s at %s (length %s, checksum %d)\n" +#~ msgstr "entrée TOC %s à %s (longueur %s, somme de contrôle %d)\n" + +#~ msgid "" +#~ "The program \"pg_dump\" is needed by %s but was not found in the\n" +#~ "same directory as \"%s\".\n" +#~ "Check your installation." +#~ msgstr "" +#~ "Le programme « pg_dump » est nécessaire à %s mais n'a pas été trouvé dans le\n" +#~ "même répertoire que « %s ».\n" +#~ "Vérifiez votre installation." + +#~ msgid "" +#~ "The program \"pg_dump\" was found by \"%s\"\n" +#~ "but was not the same version as %s.\n" +#~ "Check your installation." +#~ msgstr "" +#~ "Le programme « pg_dump » a été trouvé par « %s »\n" +#~ "mais n'a pas la même version que %s.\n" +#~ "Vérifiez votre installation." + +#~ msgid "" +#~ "WARNING:\n" +#~ " This format is for demonstration purposes; it is not intended for\n" +#~ " normal use. Files will be written in the current working directory.\n" +#~ msgstr "" +#~ "ATTENTION :\n" +#~ " Ce format est présent dans un but de démonstration ; il n'est pas prévu\n" +#~ " pour une utilisation normale. Les fichiers seront écrits dans le\n" +#~ " répertoire actuel.\n" + +#~ msgid "WARNING: could not parse reloptions array\n" +#~ msgstr "ATTENTION : n'a pas pu analyser le tableau reloptions\n" + +#~ msgid "WSAStartup failed: %d" +#~ msgstr "WSAStartup a échoué : %d" + +#~ msgid "aggregate function %s could not be dumped correctly for this database version; ignored" +#~ msgstr "la fonction d'aggrégat %s n'a pas pu être sauvegardée correctement avec cette version de la base de données ; ignorée" + +#~ msgid "allocating AH for %s, format %d\n" +#~ msgstr "allocation d'AH pour %s, format %d\n" + +#~ msgid "archive member too large for tar format\n" +#~ msgstr "membre de l'archive trop volumineux pour le format tar\n" + +#~ msgid "archiver" +#~ msgstr "archiveur" + +#~ msgid "archiver (db)" +#~ msgstr "programme d'archivage (db)" + +#~ msgid "attempting to ascertain archive format\n" +#~ msgstr "tentative d'identification du format de l'archive\n" + +#~ msgid "cannot duplicate null pointer\n" +#~ msgstr "ne peut pas dupliquer un pointeur nul\n" + +#~ msgid "cannot reopen non-seekable file\n" +#~ msgstr "ne peut pas rouvrir le fichier non cherchable\n" + +#~ msgid "cannot reopen stdin\n" +#~ msgstr "ne peut pas rouvrir stdin\n" + +#~ msgid "child process was terminated by signal %d" +#~ msgstr "le processus fils a été terminé par le signal %d" + +#~ msgid "child process was terminated by signal %s" +#~ msgstr "le processus fils a été terminé par le signal %s" + +#~ msgid "compress_io" +#~ msgstr "compression_io" + +#~ msgid "compression support is disabled in this format\n" +#~ msgstr "le support de la compression est désactivé avec ce format\n" + +#~ msgid "connecting to database \"%s\" as user \"%s\"" +#~ msgstr "connexion à la base de données « %s » en tant qu'utilisateur « %s »" + +#~ msgid "connection needs password" +#~ msgstr "la connexion nécessite un mot de passe" + +#~ msgid "connection to database \"%s\" failed: %s" +#~ msgstr "la connexion à la base de données « %s » a échoué : %s" + +#~ msgid "could not change directory to \"%s\"" +#~ msgstr "n'a pas pu accéder au répertoire « %s »" + +#~ msgid "could not change directory to \"%s\": %s" +#~ msgstr "n'a pas pu changer le répertoire par « %s » : %s" + +#~ msgid "could not close data file after reading\n" +#~ msgstr "n'a pas pu fermer le fichier de données après lecture\n" + +#~ msgid "could not close directory \"%s\": %s\n" +#~ msgstr "n'a pas pu fermer le répertoire « %s » : %s\n" + +#~ msgid "could not close large object file\n" +#~ msgstr "n'a pas pu fermer le fichier du « Large Object »\n" + +#~ msgid "could not connect to database \"%s\": %s" +#~ msgstr "n'a pas pu se connecter à la base de données « %s » : %s" + +#~ msgid "could not create directory \"%s\": %s\n" +#~ msgstr "n'a pas pu créer le répertoire « %s » : %s\n" + +#~ msgid "could not create worker thread: %s\n" +#~ msgstr "n'a pas pu créer le fil de travail: %s\n" + +#~ msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to lack of data offsets in archive" +#~ msgstr "" +#~ "n'a pas pu trouver l'identifiant de bloc %d dans l'archive --\n" +#~ "il est possible que cela soit dû à une demande de restauration dans un ordre\n" +#~ "différent, qui n'a pas pu être géré à cause d'un manque d'information de\n" +#~ "position dans l'archive" + +#~ msgid "could not find entry for pg_indexes in pg_class\n" +#~ msgstr "n'a pas pu trouver l'entrée de pg_indexes dans pg_class\n" + +#~ msgid "could not find slot of finished worker\n" +#~ msgstr "n'a pas pu trouver l'emplacement du worker qui vient de terminer\n" + +#~ msgid "could not get relation name for OID %u: %s\n" +#~ msgstr "n'a pas pu obtenir le nom de la relation pour l'OID %u: %s\n" + +#~ msgid "could not identify current directory: %s" +#~ msgstr "n'a pas pu identifier le répertoire courant : %s" + +#~ msgid "could not open large object TOC for input: %s\n" +#~ msgstr "n'a pas pu ouvrir la TOC du « Large Object » en entrée : %s\n" + +#~ msgid "could not open large object TOC for output: %s\n" +#~ msgstr "n'a pas pu ouvrir la TOC du « Large Object » en sortie : %s\n" + +#~ msgid "could not open output file \"%s\" for writing\n" +#~ msgstr "n'a pas pu ouvrir le fichier de sauvegarde « %s » en écriture\n" + +#~ msgid "could not output padding at end of tar member\n" +#~ msgstr "n'a pas pu remplir la fin du membre de tar\n" + +#~ msgid "could not parse ACL (%s) for large object %u" +#~ msgstr "n'a pas pu analyser la liste ACL (%s) du « Large Object » %u" + +#~ msgid "could not parse index collation name array" +#~ msgstr "n'a pas pu analyser le tableau des noms de collation de l'index" + +#~ msgid "could not parse index collation version array" +#~ msgstr "n'a pas pu analyser le tableau des versions de collation de l'index" + +#~ msgid "could not parse version string \"%s\"\n" +#~ msgstr "n'a pas pu analyser la chaîne de version « %s »\n" + +#~ msgid "could not read directory \"%s\": %s\n" +#~ msgstr "n'a pas pu lire le répertoire « %s » : %s\n" + +#~ msgid "could not read symbolic link \"%s\"" +#~ msgstr "n'a pas pu lire le lien symbolique « %s »" + +#~ msgid "could not reconnect to database" +#~ msgstr "n'a pas pu se reconnecter à la base de données" + +#~ msgid "could not reconnect to database: %s" +#~ msgstr "n'a pas pu se reconnecter à la base de données : %s" + +#~ msgid "could not set default_with_oids: %s" +#~ msgstr "n'a pas pu configurer default_with_oids : %s" + +#~ msgid "could not write byte\n" +#~ msgstr "n'a pas pu écrire l'octet\n" + +#~ msgid "could not write byte: %s\n" +#~ msgstr "n'a pas pu écrire un octet : %s\n" + +#~ msgid "could not write null block at end of tar archive\n" +#~ msgstr "n'a pas pu écrire le bloc nul à la fin de l'archive tar\n" + +#~ msgid "could not write to custom output routine\n" +#~ msgstr "n'a pas pu écrire vers la routine de sauvegarde personnalisée\n" + +#~ msgid "could not write to large object (result: %lu, expected: %lu)" +#~ msgstr "n'a pas pu écrire le « Large Object » (résultat : %lu, attendu : %lu)" + +#~ msgid "custom archiver" +#~ msgstr "programme d'archivage personnalisé" + +#~ msgid "directory archiver" +#~ msgstr "archiveur répertoire" + +#~ msgid "dumpBlobs(): could not open large object %u: %s" +#~ msgstr "dumpBlobs() : n'a pas pu ouvrir le « Large Object » %u : %s" + +#~ msgid "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n" +#~ msgstr "dumpDatabase() : n'a pas pu trouver pg_largeobject.relfrozenxid\n" + +#~ msgid "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n" +#~ msgstr "dumpDatabase() : n'a pas pu trouver pg_largeobject_metadata.relfrozenxid\n" + +#~ msgid "dumping a specific TOC data block out of order is not supported without ID on this input stream (fseek required)\n" +#~ msgstr "" +#~ "la sauvegarde d'un bloc de données spécifique du TOC dans le désordre n'est\n" +#~ "pas supporté sans identifiant sur ce flux d'entrée (fseek requis)\n" + +#~ msgid "entering restore_toc_entries_parallel\n" +#~ msgstr "entrée dans restore_toc_entries_parallel\n" + +#~ msgid "entering restore_toc_entries_postfork\n" +#~ msgstr "entrée dans restore_toc_entries_prefork\n" + +#~ msgid "entering restore_toc_entries_prefork\n" +#~ msgstr "entrée dans restore_toc_entries_prefork\n" + +#~ msgid "error during backup\n" +#~ msgstr "erreur lors de la sauvegarde\n" + +#~ msgid "error in ListenToWorkers(): %s\n" +#~ msgstr "erreur dans ListenToWorkers(): %s\n" + +#~ msgid "error processing a parallel work item\n" +#~ msgstr "erreur durant le traitement en parallèle d'un item\n" + +#~ msgid "failed to connect to database\n" +#~ msgstr "n'a pas pu se connecter à la base de données\n" + +#~ msgid "failed to reconnect to database\n" +#~ msgstr "la reconnexion à la base de données a échoué\n" + +#~ msgid "file archiver" +#~ msgstr "programme d'archivage de fichiers" + +#~ msgid "found more than one entry for pg_indexes in pg_class\n" +#~ msgstr "a trouvé plusieurs entrées pour pg_indexes dans la table pg_class\n" + +#~ msgid "found more than one pg_database entry for this database\n" +#~ msgstr "a trouvé plusieurs entrées dans pg_database pour cette base de données\n" + +#~ msgid "ftell mismatch with expected position -- ftell used" +#~ msgstr "ftell ne correspond pas à la position attendue -- ftell utilisé" + +#~ msgid "internal error -- neither th nor fh specified in _tarReadRaw()" +#~ msgstr "erreur interne -- ni th ni fh ne sont précisés dans _tarReadRaw()" + +#~ msgid "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n" +#~ msgstr "instruction COPY invalide -- n'a pas pu trouver « copy » dans la chaîne « %s »\n" + +#~ msgid "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n" +#~ msgstr "" +#~ "instruction COPY invalide -- n'a pas pu trouver « from stdin » dans la\n" +#~ "chaîne « %s » à partir de la position %lu\n" + +#~ msgid "invalid TOASTCOMPRESSION item: %s" +#~ msgstr "élément TOASTCOMPRESSION invalide : %s" + +#~ msgid "mismatch in actual vs. predicted file position (%s vs. %s)\n" +#~ msgstr "" +#~ "pas de correspondance entre la position réelle et celle prévue du fichier\n" +#~ "(%s vs. %s)\n" + +#~ msgid "mismatched number of collation names and versions for index" +#~ msgstr "nombre différent de noms et versions de collation pour l'index" + +#~ msgid "missing pg_database entry for database \"%s\"\n" +#~ msgstr "entrée manquante dans pg_database pour la base de données « %s »\n" + +#~ msgid "missing pg_database entry for this database\n" +#~ msgstr "entrée pg_database manquante pour cette base de données\n" + +#~ msgid "moving from position %s to next member at file position %s\n" +#~ msgstr "déplacement de la position %s vers le prochain membre à la position %s du fichier\n" + +#~ msgid "no item ready\n" +#~ msgstr "aucun élément prêt\n" + +#~ msgid "no label definitions found for enum ID %u\n" +#~ msgstr "aucune définition de label trouvée pour l'ID enum %u\n" + +#~ msgid "now at file position %s\n" +#~ msgstr "maintenant en position %s du fichier\n" + +#~ msgid "option --index-collation-versions-unknown only works in binary upgrade mode" +#~ msgstr "l'option --index-collation-versions-unknown fonctionne seulement dans le mode de mise à jour binaire" + +#~ msgid "options --inserts/--column-inserts and -o/--oids cannot be used together\n" +#~ msgstr "" +#~ "les options « --inserts/--column-inserts » et « -o/--oids » ne\n" +#~ "peuvent pas être utilisées conjointement\n" + +#~ msgid "parallel archiver" +#~ msgstr "archiveur en parallèle" + +#~ msgid "parallel_restore should not return\n" +#~ msgstr "parallel_restore ne devrait pas retourner\n" + +#~ msgid "pclose failed: %m" +#~ msgstr "échec de pclose : %m" + +#~ msgid "pclose failed: %s" +#~ msgstr "échec de pclose : %s" + +#~ msgid "query returned %d foreign server entry for foreign table \"%s\"\n" +#~ msgid_plural "query returned %d foreign server entries for foreign table \"%s\"\n" +#~ msgstr[0] "la requête a renvoyé %d entrée de serveur distant pour la table distante « %s »\n" +#~ msgstr[1] "la requête a renvoyé %d entrées de serveurs distants pour la table distante « %s »\n" + +#~ msgid "query returned %d row instead of one: %s\n" +#~ msgid_plural "query returned %d rows instead of one: %s\n" +#~ msgstr[0] "la requête a renvoyé %d ligne au lieu d'une seule : %s\n" +#~ msgstr[1] "la requête a renvoyé %d lignes au lieu d'une seule : %s\n" + +#~ msgid "query returned %d rows instead of one: %s\n" +#~ msgstr "la requête a renvoyé %d lignes au lieu d'une seule : %s\n" + +#~ msgid "query returned more than one (%d) pg_database entry for database \"%s\"\n" +#~ msgstr "" +#~ "la requête a renvoyé plusieurs (%d) entrées pg_database pour la base de\n" +#~ "données « %s »\n" + +#~ msgid "query returned no rows: %s\n" +#~ msgstr "la requête n'a renvoyé aucune ligne : %s\n" + +#~ msgid "query to get data of sequence \"%s\" returned name \"%s\"\n" +#~ msgstr "" +#~ "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé\n" +#~ "le nom « %s »\n" + +#~ msgid "query was: %s\n" +#~ msgstr "la requête était : %s\n" + +#~ msgid "read %lu byte into lookahead buffer\n" +#~ msgid_plural "read %lu bytes into lookahead buffer\n" +#~ msgstr[0] "lecture de %lu octet dans le tampon prévisionnel\n" +#~ msgstr[1] "lecture de %lu octets dans le tampon prévisionnel\n" + +#~ msgid "read TOC entry %d (ID %d) for %s %s\n" +#~ msgstr "lecture de l'entrée %d de la TOC (ID %d) pour %s %s\n" + +#~ msgid "reading extended statistics for table \"%s.%s\"\n" +#~ msgstr "lecture des statistiques étendues pour la table « %s.%s »\n" + +#~ msgid "reading policies for table \"%s.%s\"" +#~ msgstr "lecture des politiques pour la table « %s.%s »" + +#~ msgid "reading publication membership for table \"%s.%s\"" +#~ msgstr "lecture des appartenances aux publications pour la table « %s.%s »" + +#~ msgid "reading row security enabled for table \"%s.%s\"" +#~ msgstr "lecture de l'activation de la sécurité niveau ligne pour la table « %s.%s »" + +#~ msgid "reconnection to database \"%s\" failed: %s" +#~ msgstr "reconnexion à la base de données « %s » échouée : %s" + +#~ msgid "reducing dependencies for %d\n" +#~ msgstr "réduction des dépendances pour %d\n" + +#~ msgid "requested %d byte, got %d from lookahead and %d from file\n" +#~ msgid_plural "requested %d bytes, got %d from lookahead and %d from file\n" +#~ msgstr[0] "%d octet requis, %d obtenu de « lookahead » et %d du fichier\n" +#~ msgstr[1] "%d octets requis, %d obtenus de « lookahead » et %d du fichier\n" + +#~ msgid "restoring large object OID %u\n" +#~ msgstr "restauration du « Large Object » d'OID %u\n" + +#~ msgid "saving default_toast_compression = %s" +#~ msgstr "sauvegarde de default_toast_compression = %s" + +#~ msgid "saving large object properties\n" +#~ msgstr "sauvegarde des propriétés des « Large Objects »\n" + +#~ msgid "schema with OID %u does not exist\n" +#~ msgstr "le schéma d'OID %u n'existe pas\n" + +#~ msgid "select() failed: %m" +#~ msgstr "échec de select() : %m" + +#~ msgid "select() failed: %s\n" +#~ msgstr "échec de select() : %s\n" + +#~ msgid "server version must be at least 7.3 to use schema selection switches\n" +#~ msgstr "" +#~ "le serveur doit être de version 7.3 ou supérieure pour utiliser les options\n" +#~ "de sélection du schéma\n" + +#~ msgid "setting owner and privileges for %s \"%s\"\n" +#~ msgstr "réglage du propriétaire et des droits pour %s « %s »\n" + +#~ msgid "setting owner and privileges for %s \"%s.%s\"\n" +#~ msgstr "réglage du propriétaire et des droits pour %s « %s.%s»\n" + +#~ msgid "skipping tar member %s\n" +#~ msgstr "omission du membre %s du tar\n" + +#~ msgid "sorter" +#~ msgstr "tri" + +#~ msgid "tar archiver" +#~ msgstr "archiveur tar" + +#~ msgid "terminated by user\n" +#~ msgstr "terminé par l'utilisateur\n" + +#~ msgid "transferring dependency %d -> %d to %d\n" +#~ msgstr "transfert de la dépendance %d -> %d vers %d\n" + +#~ msgid "unexpected end of file\n" +#~ msgstr "fin de fichier inattendu\n" + +#~ msgid "unrecognized collation provider: %s\n" +#~ msgstr "fournisseur de collationnement non reconnu : %s\n" + +#~ msgid "unrecognized command on communication channel: %s\n" +#~ msgstr "commande inconnue sur le canal de communucation: %s\n" + +#~ msgid "worker is terminating\n" +#~ msgstr "le worker est en cours d'arrêt\n" + +#~ msgid "worker process crashed: status %d\n" +#~ msgstr "crash du processus worker : statut %d\n" diff --git a/src/bin/pg_dump/po/ja.po b/src/bin/pg_dump/po/ja.po new file mode 100644 index 0000000..0f642b6 --- /dev/null +++ b/src/bin/pg_dump/po/ja.po @@ -0,0 +1,2744 @@ +# pg_dump.po +# Japanese message translation file for pg_dump +# +# Copyright (C) 2011-2022 PostgreSQL Global Development Group +# +# Shigehiro Honda , 2005. +# +# This file is distributed under the same license as the PostgreSQL package. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL 14)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-05-12 14:05+0900\n" +"PO-Revision-Date: 2022-06-14 17:36+0900\n" +"Last-Translator: Kyotaro Horiguchi \n" +"Language-Team: Japan PostgreSQL Users Group \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Poedit 1.8.13\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "致命的エラー: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "エラー: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "警告: " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "カレントディレクトリを確認できませんでした: %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "不正なバイナリ\"%s\"" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "バイナリ\"%s\"を読み取れませんでした" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "実行対象の\"%s\"が見つかりませんでした" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "ディレクトリ\"%s\"に移動できませんでした: %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "シンボリックリンク\"%s\"を読めませんでした: %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() が失敗しました: %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "メモリ不足" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "メモリ不足\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nullポインタは複製できません (内部エラー)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "コマンドは実行可能形式ではありません" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "コマンドが見つかりません" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "子プロセスが終了コード%dで終了しました" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "子プロセスが例外0x%Xで終了しました" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "子プロセスはシグナル%dにより終了しました: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "子プロセスは認識できないステータス%dで終了しました" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "機能拡張を読み込んでいます" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "機能拡張の構成要素を特定しています" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "スキーマを読み込んでいます" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "ユーザー定義テーブルを読み込んでいます" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "ユーザー定義関数を読み込んでいます" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "ユーザー定義型を読み込んでいます" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "手続き言語を読み込んでいます" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "ユーザー定義集約関数を読み込んでいます" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "ユーザー定義演算子を読み込んでいます" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "ユーザー定義アクセスメソッドを読み込んでいます" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "ユーザー定義演算子クラスを読み込んでいます" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "ユーザー定義演算子族を読み込んでいます" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "ユーザー定義のテキスト検索パーサを読み込んでいます" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "ユーザー定義のテキスト検索テンプレートを読み込んでいます" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "ユーザー定義のテキスト検索辞書を読み込んでいます" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "ユーザー定義のテキスト検索設定を読み込んでいます" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "ユーザー定義の外部データラッパーを読み込んでいます" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "ユーザー定義の外部サーバーを読み込んでいます" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "デフォルト権限設定を読み込んでいます" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "ユーザー定義の照合順序を読み込んでいます" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "ユーザー定義の変換を読み込んでいます" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "型キャストを読み込んでいます" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "変換を読み込んでいます" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "テーブル継承情報を読み込んでいます" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "イベントトリガを読み込んでいます" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "機能拡張構成テーブルを探しています" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "継承関係を検索しています" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "対象テーブルの列情報を読み込んでいます" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "子テーブルの継承列にフラグを設定しています" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "インデックスを読み込んでいます" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "パーティション親テーブルのインデックスにフラグを設定しています" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "拡張統計情報を読み込んでいます" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "制約を読み込んでいます" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "トリガを読み込んでいます" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "書き換えルールを読み込んでいます" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "ポリシを読み込んでいます" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "パブリケーションを読み込んでいます" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "パブリケーションの構成要素を読み込んでいます" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "サブスクリプションを読み込んでいます" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "テーブル\"%2$s\"用の親テーブルの数%1$dが不正です" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "健全性検査に失敗しました、テーブル\"%2$s\"(OID %3$u)の親のOID %1$uがありません" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "数値配列\"%s\"のパースに失敗しました: 要素が多すぎます" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "数値配列\"%s\"のパースに失敗しました: 数値に不正な文字が含まれています" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "不正な圧縮コード: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "zlibサポートなしでビルドされています" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "圧縮ライブラリを初期化できませんでした: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "圧縮ストリームをクローズできませんでした: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "データを圧縮できませんでした: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "データを伸長できませんでした: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "圧縮ライブラリをクローズできませんでした: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "入力ファイルから読み込めませんでした: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "入力ファイルから読み込めませんでした: ファイルの終端" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s()が失敗しました: エラーコード %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "通信チャンネルを作成できませんでした: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "ワーカープロセスを作成できませんでした: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "リーダーから認識不能のコマンドを受信しました: \"%s\"" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "ワーカーから不正なメッセージを受信しました: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"リレーション\"%s\"のロックを獲得できませんでした。\n" +"通常これは、pg_dumpの親プロセスが初期のACCESS SHAREロックを獲得した後にだれかがテーブルに対してACCESS EXCLUSIVEロックを要求したことを意味しています。" + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "ワーカープロセスが突然終了しました" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "通信チャンネルに書き込めませんでした: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: ソケットを作成できませんでした: エラーコード %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: バインドできませんでした: エラーコード %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: リッスンできませんでした: エラーコード %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s()が失敗しました: エラーコード %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: 第二ソケットを作成できませんでした: エラーコード %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: ソケットを接続できませんでした: エラーコード %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: 接続を受け付けられませんでした: エラーコード %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "出力ファイルをクローズできませんでした: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "アーカイブ項目が正しいセクション順ではありません" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "想定外のセクションコード %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "このアーカイブファイル形式での並列リストアはサポートしていません" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "8.0 より古い pg_dump で作られたアーカイブでの並列リストアはサポートしていません" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "圧縮アーカイブからのリストアができません(このインストールは圧縮をサポートしていません)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "リストアのためデータベースに接続しています" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "1.3より古いアーカイブではデータベースへの直接接続はサポートされていません" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "暗黙的にデータのみのリストアを行います" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "%s %sを削除しています" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "文\"%s\"中に IF EXISTS を挿入すべき場所が見つかりませでした" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "オリジナルのダンプファイルからの警告: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "%s \"%s.%s\"を作成しています" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "%s \"%s\"を作成しています" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "新しいデータベース\"%s\"に接続しています" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "%sを処理しています" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"のデータを処理しています" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "%s %sを実行しています" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "%sのトリガを無効にしています" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "%sのトリガを有効にしています" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "内部エラー -- WriteDataはDataDumperルーチンのコンテクスト外では呼び出せません" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "選択した形式ではラージオブジェクト出力をサポートしていません" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "%d個のラージオブジェクトをリストアしました" +msgstr[1] "%d個のラージオブジェクトをリストアしました" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "OID %uのラージオブジェクトをリストアしています" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "ラージオブジェクト %u を作成できませんでした: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "ラージオブジェクト %u をオープンできませんでした: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "TOCファイル\"%s\"をオープンできませんでした: %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "行を無視しました: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "ID %dのエントリがありませんでした" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "TOCファイルをクローズできませんでした: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "出力ファイル\"%s\"をオープンできませんでした: %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "出力ファイルをオープンできませんでした: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "ラージオブジェクトデータを%zuバイト書き出しました(結果は%d)" +msgstr[1] "ラージオブジェクトデータを%zuバイト書き出しました(結果は%d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "ラージオブジェクトに書き込めませんでした: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "初期化中:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "TOC処理中:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "終了処理中:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "TOCエントリ%d; %u %u %s %s %s から" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "不正なdumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "TABLE DATA項目に対する不正なテーブルdumpId" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "想定外のデータオフセットフラグ %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "ダンプファイルのファイルオフセットが大きすぎます" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "ディレクトリ名が長すぎます: \"%s\"" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "ディレクトリ\"%s\"は有効なアーカイブではないようです(\"toc.dat\"がありません)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "入力ファイル\"%s\"をオープンできませんでした: %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "入力ファイルをオープンできませんでした: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "入力ファイルを読み込めませんでした: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "入力ファイルが小さすぎます(読み取り%lu、想定は 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "入力ファイルがテキスト形式のダンプのようです。psqlを使用してください。" + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "入力ファイルが有効なアーカイブではないようです(小さすぎる?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "入力ファイルが有効なアーカイブではないようです" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "入力ファイルをクローズできませんでした: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "認識不能のファイル形式\"%d\"" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "項目 %d %s %s の処理が完了" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "ワーカープロセスの処理失敗: 終了コード %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "エントリID%dは範囲外です -- おそらくTOCの破損です" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "WITH OIDSと定義されたテーブルのリストアは今後サポートされません" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "認識不能のエンコーディング\"%s\"" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "不正なENCODING項目: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "不正なSTDSTRINGS項目: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "スキーマ \"%s\"が見つかりません" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "テーブル\"%s\"が見つかりません" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "インデックス\"%s\"が見つかりません" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "関数\"%s\"が見つかりません" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "トリガ\"%s\"が見つかりません" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "セッションユーザーを\"%s\"に設定できませんでした: %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "search_pathを\"%s\"に設定できませんでした: %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "default_tablespaceを\"%s\"に設定できませんでした: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "default_table_access_methodを設定できませんでした: %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "オブジェクトタイプ%sに対する所有者の設定方法がわかりません" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "ファイルヘッダにマジック文字列がありませんでした" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "ファイルヘッダ内のバージョン(%d.%d)はサポートされていません" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "整数のサイズ(%lu)に関する健全性検査が失敗しました" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "アーカイブはより大きなサイズの整数を持つマシンで作成されました、一部の操作が失敗する可能性があります" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "想定した形式(%d)はファイル内にある形式(%d)と異なります" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "アーカイブは圧縮されていますが、このインストールでは圧縮をサポートしていません -- 利用できるデータはありません" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "ヘッダ内の作成日付が不正です" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "項目 %d %s %s を処理しています" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "メインの並列ループに入ります" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "項目 %d %s %s をスキップしています" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "項目 %d %s %s に着手します" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "メインの並列ループが終了しました" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "やり残し項目 %d %s %s を処理しています" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "テーブル\"%s\"を作成できませんでした、このテーブルのデータは復元されません" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "ラージオブジェクトのOIDが不正です" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "ファイルシーク中にエラーがありました: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "データブロック%dのシーク位置が間違っています" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "アーカイブの探索中に認識不能のデータブロックタイプ(%d)がありました" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "アーカイブ中にブロックID %d がありません -- おそらくリストア要求が順不同だったためですが、入力ファイルがシーク不可なため処理できません" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "アーカイブ内にブロック ID %d がありませんでした -- おそらくアーカイブが壊れています" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "データ読み込み時に想定外のブロックID(%d)がありました --想定は%d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "アーカイブのりストア中に認識不可のデータブロックタイプ%dがありました" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "入力ファイルから読み込めませんでした: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "アーカイブファイルのシーク位置を決定できませんでした: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "アーカイブファイルをクローズできませんでした: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "入力アーカイブだけが再オープン可能です" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "標準入力からの並列リストアはサポートされていません" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "シーク不可のファイルからの並列リストアはサポートされていません" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "アーカイブファイルのシークができませんでした: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "圧縮処理が有効です" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "libpqからserver_versionを取得できませんでした" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "サーバーバージョン: %s、%s バージョン: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "サーバーバージョンの不一致のため処理を中断します" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "データベースはすでに接続済みです" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "パスワード: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "データベースへの接続ができませんでした" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "再接続に失敗しました: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "問い合わせが失敗しました: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "問い合わせ: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "問い合わせが1行ではなく%d行返しました: %s" +msgstr[1] "問い合わせが1行ではなく%d行返しました: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sコマンド: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "問い合わせを実行できませんでした" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "PQputCopyData からエラーが返されました: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "PQputCopyEnd からエラーが返されました: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "テーブル\"%s\"へのコピーに失敗しました: %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "ファイル\"%s\"をCOPY中に想定していない余分な結果がありました" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "データベーストランザクションを開始できませんでした" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "データベーストランザクションをコミットできませんでした" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "出力ディレクトリが指定されていません" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "出力ファイルに書き込めませんでした: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "データファイルをクローズできませんでした: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "データファイル\"%s\"をクローズできませんでした: %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "ラージオブジェクトTOCファイル\"%s\"を入力用としてオープンできませんでした: %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "ラージオブジェクトTOCファイル\"%s\"の中に不正な行がありました: \"%s\"" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "ラージオブジェクトTOCファイル\"%s\"の読み取り中にエラーがありました" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "ラージオブジェクトTOCファイル\"%s\"をクローズできませんでした: %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "blobデータファイルをクローズできませんでした: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "blobのTOCファイルに書き出せませんでした" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "blobのTOCファイルをクローズできませんでした: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "ファイル名が長すぎます: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "この形式は読み込めません" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "TOCファイル\"%s\"を出力用にオープンできませんでした: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "TOCファイルを出力用にオープンできませんでした: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "tar アーカイブ形式では圧縮をサポートしていません" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "TOCファイル\"%s\"を入力用にオープンできませんでした: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "TOCファイルを入力用にオープンできませんでした: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "アーカイブ内にファイル\"%s\"がありませんでした" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "一時ファイル名を生成できませんでした: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "一時ファイルをオープンできませんでした" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "tarメンバをクローズできませんでした: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "想定外のCOPY文の構文: \"%s\"" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "ラージオブジェクトの不正なOID(%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "一時ファイルを開けませんでした: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "実際の長さ(%s)が想定(%s)と一致しません" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "tar アーカイブ内でファイル\"%s\"のヘッダがありませんでした" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "このアーカイブ形式では、順不同でのデータのリストアはサポートされていません: \"%s\"は必要ですが、アーカイブファイル内で\"%s\"より前に来ました。" + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "不完全なtarヘッダがありました(%luバイト)" +msgstr[1] "不完全なtarヘッダがありました(%luバイト)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "破損したtarヘッダが%sにありました(想定 %d、算出結果 %d) ファイル位置 %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "認識不可のセクション名: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "詳細は\"%s --help\"で確認してください。\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "on_exit_nicelyスロットが足りません" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "圧縮レベルは 0..9 の範囲でなければなりません" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digitsは -15..3 の範囲でなければなりません" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insertは%d..%dの範囲でなければなりません" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "コマンドライン引数が多すぎます (先頭は\"%s\")" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "-s/--schema-only と -a/--data-only オプションは同時には使用できません" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "-s/--schema-only と --include-foreign-data オプションは同時には使用できません" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "オプション --include-foreign-data はパラレルバックアップではサポートされません" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "-c/--clean と -a/--data-only オプションは同時には使用できません" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "--if-existsは -c/--clean の指定が必要です" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "--on-conflict-do-nothingオプションは--inserts、--rows-per-insert または --column-insertsを必要とします" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "圧縮が要求されましたがこのインストールでは利用できません -- アーカイブは圧縮されません" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "不正な並列ジョブ数" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "並列バックアップはディレクトリ形式でのみサポートされます" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"同期スナップショットはこのサーバーバージョンではサポートされていません。\n" +"同期スナップショットが不要ならば--no-synchronized-snapshotsを付けて\n" +"実行してください。" + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "スナップショットのエクスポートはこのサーバーバージョンではサポートされません" + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "最後の組み込みOIDは%u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "合致するスキーマが見つかりません" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "合致するテーブルが見つかりません" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "合致する機能拡張が見つかりません" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%sはデータベースをテキストファイルまたはその他の形式でダンプします。\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "使用方法:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [オプション]... [データベース名]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"一般的なオプション:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=ファイル名 出力ファイルまたはディレクトリの名前\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p 出力ファイルの形式(custom, directory, tar, \n" +" plain text(デフォルト))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM ダンプ時に指定した数の並列ジョブを使用\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 冗長モード\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version バージョン情報を表示して終了\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 圧縮形式における圧縮レベル\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT テーブルロックをTIMEOUT待ってから失敗\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync 変更のディスクへの安全な書き出しを待機しない\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help このヘルプを表示して終了\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"出力内容を制御するためのオプション:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only データのみをダンプし、スキーマをダンプしない\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs ダンプにラージオブジェクトを含める\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs ダンプにラージオブジェクトを含めない\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean 再作成前にデータベースオブジェクトを整理(削除)\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create ダンプにデータベース生成用コマンドを含める\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=PATTERN 指定した機能拡張のみをダンプ\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=ENCODING ENCODING符号化方式でデータをダンプ\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATTERN 指定したスキーマのみをダンプ\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN 指定したスキーマをダンプしない\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner プレインテキスト形式で、オブジェクト所有権の復元を\n" +" 行わない\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only スキーマのみをダンプし、データはダンプしない\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr "" +" -S, --superuser=NAME プレインテキスト形式で使用するスーパーユーザーの\n" +" 名前\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATTERN 指定したテーブルのみをダンプ\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATTERN 指定したテーブルをダンプしない\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges 権限(grant/revoke)をダンプしない\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade アップグレードユーティリティ専用\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts 列名指定のINSERTコマンドでデータをダンプ\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr "" +" --disable-dollar-quoting ドル記号による引用符付けを禁止、SQL標準の引用符\n" +" 付けを使用\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers データのみのリストアの際にトリガを無効化\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security 行セキュリティを有効化(ユーザーがアクセス可能な\n" +" 内容のみをダンプ)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATTERN 指定したテーブルのデータをダンプしない\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM extra_float_digitsの設定を上書きする\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists オブジェクト削除の際に IF EXISTS を使用\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=PATTERN\n" +" PATTERNに合致する外部サーバー上の外部テーブルの\n" +" データを含める\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts COPYではなくINSERTコマンドでデータをダンプ\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root 子テーブルをルートテーブル経由でロード\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments コメントをダンプしない\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications パブリケーションをダンプしない\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels セキュリティラベルの割り当てをダンプしない\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions サブスクリプションをダンプしない\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots 並列ジョブにおいて同期スナップショットを使用しない\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces テーブルスペースの割り当てをダンプしない\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression TOAST圧縮方式をダンプしない\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data 非ログテーブルのデータをダンプしない\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing INSERTコマンドにON CONFLICT DO NOTHINGを付加\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers すべての識別子をキーワードでなかったとしても\n" +" 引用符で囲む\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS INSERT毎の行数; --insertsを暗黙的に設定\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECTION 指定したセクション(データ前、データ、データ後)を\n" +" ダンプする\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable ダンプを異常なく実行できるようになるまで待機\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT ダンプに指定のスナップショットを使用する\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names テーブル/スキーマの対象パターンが最低でも\n" +" 一つの実体に合致することを必須とする\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" 所有者をセットする際、ALTER OWNER コマンドの代わり\n" +" に SET SESSION AUTHORIZATION コマンドを使用\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"接続オプション:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME ダンプするデータベース\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME データベースサーバーのホストまたはソケットディレクトリ\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT データベースサーバーのポート番号\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NAME 指定したデータベースユーザーで接続\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password パスワード入力を要求しない\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password パスワードプロンプトの強制表示 (本来は自動的に表示)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME ダンプの前に SET ROLE を行う\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"データベース名が指定されなかった場合、環境変数PGDATABASEが使用されます\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "バグは<%s>に報告してください。\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s ホームページ: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "不正なクライアントエンコーディング\"%s\"が指定されました" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"同期スナップショットはこのサーバーバージョンではサポートされていません。\n" +"同期スナップショットが不要ならば--no-synchronized-snapshotsを付けて\n" +"実行してください。" + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "不正な出力形式\"%s\"が指定されました" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "修飾名が不適切です(ドット区切りの名前が多すぎます): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "パターン\"%s\"に合致するスキーマが見つかりません" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "パターン \"%s\"に合致する機能拡張が見つかりません" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "パターン\"%s\"に合致する外部サーバーが見つかりません" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "リレーション名が不適切です(ドット区切りの名前が多すぎます): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "パターン \"%s\"に合致するテーブルが見つかりません" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "現在データベースに接続していません。" + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "データベース間の参照は実装されていません: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "テーブル \"%s.%s\"の内容をダンプしています" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "テーブル\"%s\"の内容のダンプに失敗: PQgetCopyData()が失敗しました。" + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "サーバーのエラーメッセージ: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "コマンド: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "テーブル\"%s\"の内容のダンプに失敗: PQgetResult()が失敗しました。" + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "テーブル\"%s\"から間違った数のフィールドを取得しました" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "データベース定義を保存しています" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "encoding = %s を保存しています" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "standard_conforming_strings = %s を保存しています" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "current_schemas()の結果をパースできませんでした" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "search_path = %s を保存しています" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "ラージオブジェクトを読み込んでいます" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "ラージオブジェクトを保存しています" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "ラージオブジェクト %u を読み取り中にエラーがありました: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "行レベルセキュリティポリシーを読み取ります" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "想定外のポリシコマンドタイプ: \"%c\"" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "パブリケーション\"%s\"の所有者が不正なようです" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "現在のユーザーがスーパーユーザーではないため、サブスクリプションはダンプされません" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "サブスクリプション\"%s\"の所有者が無効なようです" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "subpublications配列をパースできませんでした" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "%s %sの親となる機能拡張がありませんでした" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "スキーマ\"%s\"の所有者が無効なようです" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "OID %uのスキーマは存在しません" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "データ型\"%s\"の所有者が無効なようです" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "演算子\"%s\"の所有者が無効なようです" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "演算子クラス\"%s\"の所有者が無効なようです" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "演算子族\"%s\"の所有者が無効なようです" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "集約関数\"%s\"の所有者が無効なようです" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "関数\"%s\"の所有者が無効なようです" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "テーブル\"%s\"の所有者が無効なようです" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "健全性検査に失敗しました、OID %2$u であるシーケンスの OID %1$u である親テーブルがありません" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"のインデックスを読み込んでいます" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"の外部キー制約を読み込んでいます" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "健全性検査に失敗しました、OID %2$u であるpg_rewriteエントリのOID %1$u である親テーブルが見つかりません" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"のトリガを読み込んでいます" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "問い合わせがテーブル\"%2$s\"上の外部キートリガ\"%1$s\"の参照テーブル名としてNULLを返しました(テーブルのOID: %3$u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"の列と型を探しています" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "テーブル\"%s\"の列番号が不正です" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"のデフォルト式を探しています" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "テーブル\"%2$s\"用のadnumの値%1$dが不正です" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "テーブル\"%s.%s\"の検査制約を探しています" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "テーブル\"%2$s\"で想定する検査制約は%1$d個でしたが、%3$dありました" +msgstr[1] "テーブル\"%2$s\"で想定する検査制約は%1$d個でしたが、%3$dありました" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(システムカタログが破損している可能性があります)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "データ型\"%s\"のtyptypeが不正なようです" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "proargmodes配列内におかしな値があります" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "proallargtypes配列のパースができませんでした" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "proargmodes配列のパースができませんでした" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "proargnames配列のパースができませんでした" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "proconfig配列のパースができませんでした" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "関数\"%s\"のprovolatileの値が認識できません" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "関数\"%s\"のproparallel値が認識できません" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "OID %uの関数の関数定義が見つかりませんでした" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "pg_cast.castfuncまたはpg_cast.castmethodフィールドの値がおかしいです" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "pg_cast.castmethod フィールドの値がおかしいです" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "おかしな変換定義、trffromsql か trftosql の少なくとも一方は非ゼロであるはずです" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "pg_cast.castmethod フィールドの値がおかしいです" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "pg_cast.castmethod フィールドの値がおかしいです" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "後置演算子はサポートされていません (演算子 \"%s\")" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "OID %sの演算子がありませんでした" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "アクセスメソッド\"%2$s\"の不正なタイプ\"%1$c\"" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "認識できないの照合順序プロバイダ: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "集約\"%s\"のaggfinalmodifyの値が識別できません" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "集約\"%s\"のaggmfinalmodifyの値が識別できません" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "デフォルト権限設定中の認識できないオブジェクト型: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "デフォルトの ACL リスト(%s)をパースできませんでした" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "オブジェクト\"%3$s\"(%4$s)の初期GRANT ACLリスト(%1$s)または初期REVOKE ACLリスト(%2$s)をパースできませんでした" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "オブジェクト\"%3$s\"(%4$s)のGRANT ACLリスト(%1$s)またはREVOKE ACLリスト(%2$s)をパースできませんでした" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "ビュー\"%s\"の定義を取り出すための問い合わせがデータを返却しませんでした" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "ビュー\"%s\"の定義を取り出すための問い合わせが2つ以上の定義を返却しました" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "ビュー\"%s\"の定義が空のようです(長さが0)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDSは今後サポートされません(テーブル\"%s\")" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "テーブル\"%2$s\"の列番号%1$dは不正です" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "インデックス統計カラムをパースできませんでした" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "インデックス統計値をパースできませんでした" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "インデックス統計情報における列数と値の数の不一致" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "制約\"%s\"のインデックスが見つかりません" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "制約のタイプが識別できません: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "シーケンス\"%s\"のデータを得るための問い合わせが%d行返却しました(想定は1)" +msgstr[1] "シーケンス\"%s\"のデータを得るための問い合わせが%d行返却しました(想定は1)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "認識されないシーケンスの型\"%s\"" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "想定外のtgtype値: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "テーブル\"%3$s\"上のトリガ\"%2$s\"の引数文字列(%1$s)が不正です" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "テーブル\"%2$s\"のルール\"%1$s\"を得るための問い合わせが失敗しました: 間違った行数が返却されました" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "親の機能拡張%uが見つかりません" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "機能拡張設定配列をパースできませんでした" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "機能拡張条件配列をパースできませんでした" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "機能拡張における設定項目数と条件の数の不一致" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "データの依存データを読み込んでいます" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "参照元オブジェクト%u %uがありません" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "参照先オブジェクト%u %uがありません" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "reloptions配列をパースできませんでした" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "不正なdumpId %d" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "不正な依存関係 %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "依存関係のループが見つかりませんでした" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "次のテーブルの中で外部キー制約の循環があります: " +msgstr[1] "次のテーブルの中で外部キー制約の循環があります: " + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "--disable-triggersの使用または一時的な制約の削除を行わずにこのダンプをリストアすることはできないかもしれません。" + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "この問題を回避するために--data-onlyダンプの代わりに完全なダンプを使用することを検討してください。" + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "以下の項目の間の依存関係のループを解決できませんでした:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"%2$sにはプログラム\"%1$s\"が必要ですが、\"%3$s\"と同じディレクトリ\n" +"にはありませんでした。\n" +"インストールの状態を確認してください。" + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じ\n" +"バージョンではありませんでした。\n" +"インストールの状態を確認してください。" + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "--exclude-database オプションは -g/--globals-only、-r/--roles-only もしくは -t/--tablespaces-only と一緒には使用できません" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "-g/--globals-onlyと-r/--roles-onlyオプションは同時に使用できません" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "-g/--globals-onlyと-t/--tablespaces-onlyオプションは同時に使用できません" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "-r/--roles-onlyと-t/--tablespaces-onlyオプションは同時に使用できません" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "データベース\"%s\"へ接続できませんでした" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"\"postgres\"または\"template1\"データベースに接続できませんでした\n" +"代わりのデータベースを指定してください。" + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%sはPostgreSQLデータベースクラスタをSQLスクリプトファイルに展開します。\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [オプション]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=ファイル名 出力ファイル名\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean 再作成前にデータベースを整理(削除)\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr "" +" -g, --globals-only グローバルオブジェクトのみをダンプし、\n" +" データベースをダンプしない\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner オブジェクトの所有権の復元を省略\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only ロールのみをダンプ。\n" +" データベースとテーブル空間をダンプしない\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME ダンプで使用するスーパーユーザーのユーザー名を指定\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only テーブル空間のみをダンプ。データベースとロールを\n" +" ダンプしない\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=PATTERN PATTERNに合致する名前のデータベースを除外\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords ロールのパスワードをダンプしない\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONSTR 接続文字列を用いた接続\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME 代替のデフォルトデータベースを指定\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"-f/--file が指定されない場合、SQLスクリプトは標準出力に書き出されます。\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "\"pg_\"で始まるロール名はスキップされました(%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "テーブル空間\"%2$s\"のACLリスト(%1$s)をパースできませんでした" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "データベース\"%s\"を除外します" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "データベース\"%s\"をダンプしています" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "データベース\"%s\"のダンプが失敗しました、終了します" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "出力ファイル\"%s\"を再オープンできませんでした: %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "\"%s\"を実行しています" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "サーバーバージョンを取得できませんでした" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "サーバーバージョン\"%s\"をパースできませんでした" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "%s を実行しています" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "-d/--dbnameと-f/--fileのどちらか一方が指定されていなければなりません" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "オプション-d/--dbnameと-f/--fileは同時に使用できません" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "オプション-C/--createと-1/--single-transactionとは同時には使用できません" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "並列ジョブ数の最大値は%dです" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "--single-transaction と複数ジョブは同時には指定できません" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "アーカイブ形式\"%s\"が認識できません; \"c\"、\"d\"または\"t\"を指定してください" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "リストア中に無視されたエラー数: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%sはpg_dumpで作成したアーカイブからPostgreSQLデータベースをリストアします。\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [オプション]... [ファイル]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME 接続するデータベース名\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FILENAME 出力ファイル名(- で標準出力)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t バックアップファイル形式 (自動的に決定されるはず)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list アーカイブのTOCの要約を表示\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 冗長モード\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version バージョン情報を表示して終了\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help このヘルプを表示して終了\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"リストア制御用のオプション:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only データのみをリストア、スキーマをリストアしない\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create 対象のデータベースを作成\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error エラー時に終了、デフォルトは継続\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME 指名したインデックスをリストア\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM リストア時に指定した数の並列ジョブを使用\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FILENAME このファイルの内容に従って SELECT や\n" +" 出力のソートを行う\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME 指定したスキーマのオブジェクトのみをリストア\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME 指定したスキーマのオブジェクトはリストアしない\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) 指名された関数をリストア\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only スキーマのみをリストア。データをリストアしない\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAME トリガを無効にするためのスーパーユーザーの名前\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr "" +" -t, --table=NAME 指名したリレーション(テーブル、ビューなど)を\n" +" リストア\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAME 指名したトリガをリストア\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges アクセス権限(grant/revoke)の復元を省略\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction 単一のトランザクションとしてリストア\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security 行セキュリティを有効にします\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments コメントをリストアしない\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr " --no-data-for-failed-tables 作成できなかったテーッブルのデータはリストアしない\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications パブリケーションをリストアしない\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels セキュリティラベルをリストアしない\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions サブスクリプションをリストアしない\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces テーブル空間の割り当てをリストアしない\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr "" +" --section=SECTION 指定されたセクション (pre-data, data, または\n" +" post-data) をリストア\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME リストアの前に SET ROLE を行う\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +" -I, -n, -N, -P, -t, -T および --section オプションは組み合わせて複数回\n" +"指定することで複数のオブジェクトを指定できます。\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"入力ファイル名が指定されない場合、標準入力が使用されます。\n" +"\n" + +#~ msgid "reading policies for table \"%s.%s\"" +#~ msgstr "テーブル\"%s.%s\"のポリシを読み込んでいます" + +#~ msgid "reading row security enabled for table \"%s.%s\"" +#~ msgstr "テーブル\"%s.%s\"で有効な行セキュリティ設定を読み込んでいます" diff --git a/src/bin/pg_dump/po/ko.po b/src/bin/pg_dump/po/ko.po new file mode 100644 index 0000000..f533f7e --- /dev/null +++ b/src/bin/pg_dump/po/ko.po @@ -0,0 +1,2821 @@ +# Korean message translation file for PostgreSQL pg_dump +# Ioseph Kim , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL) 13\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2020-10-05 20:46+0000\n" +"PO-Revision-Date: 2020-10-06 13:40+0900\n" +"Last-Translator: Ioseph Kim \n" +"Language-Team: Korean Team \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../../../src/common/logging.c:236 +#, c-format +msgid "fatal: " +msgstr "심각: " + +#: ../../../src/common/logging.c:243 +#, c-format +msgid "error: " +msgstr "오류: " + +#: ../../../src/common/logging.c:250 +#, c-format +msgid "warning: " +msgstr "경고: " + +#: ../../common/exec.c:137 ../../common/exec.c:254 ../../common/exec.c:300 +#, c-format +msgid "could not identify current directory: %m" +msgstr "현재 디렉터리를 알 수 없음: %m" + +#: ../../common/exec.c:156 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "잘못된 바이너리 파일 \"%s\"" + +#: ../../common/exec.c:206 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "\"%s\" 바이너리 파일을 읽을 수 없음" + +#: ../../common/exec.c:214 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "실행 할 \"%s\" 파일을 찾을 수 없음" + +#: ../../common/exec.c:270 ../../common/exec.c:309 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "\"%s\" 이름의 디렉터리로 이동할 수 없습니다: %m" + +#: ../../common/exec.c:287 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m" + +#: ../../common/exec.c:410 +#, c-format +msgid "pclose failed: %m" +msgstr "pclose 실패: %m" + +#: ../../common/exec.c:539 ../../common/exec.c:584 ../../common/exec.c:676 +msgid "out of memory" +msgstr "메모리 부족" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "명령을 실행할 수 없음" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "해당 명령어 없음" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "하위 프로세스가 종료되었음, 종료 코드 %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "0x%X 예외처리로 하위 프로세스가 종료되었음" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "하위 프로세스가 종료되었음, 시그널 %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "하위 프로세스가 종료되었음, 알수 없는 상태 %d" + +#: common.c:121 +#, c-format +msgid "reading extensions" +msgstr "확장 기능 읽는 중" + +#: common.c:125 +#, c-format +msgid "identifying extension members" +msgstr "확장 멤버를 식별 중" + +#: common.c:128 +#, c-format +msgid "reading schemas" +msgstr "스키마들을 읽는 중" + +#: common.c:138 +#, c-format +msgid "reading user-defined tables" +msgstr "사용자 정의 테이블들을 읽는 중" + +#: common.c:145 +#, c-format +msgid "reading user-defined functions" +msgstr "사용자 정의 함수들 읽는 중" + +#: common.c:150 +#, c-format +msgid "reading user-defined types" +msgstr "사용자 정의 자료형을 읽는 중" + +#: common.c:155 +#, c-format +msgid "reading procedural languages" +msgstr "프로시쥬얼 언어를 읽는 중" + +#: common.c:158 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "사용자 정의 집계 함수를 읽는 중" + +#: common.c:161 +#, c-format +msgid "reading user-defined operators" +msgstr "사용자 정의 연산자를 읽는 중" + +#: common.c:165 +#, c-format +msgid "reading user-defined access methods" +msgstr "사용자 정의 접근 방법을 읽는 중" + +#: common.c:168 +#, c-format +msgid "reading user-defined operator classes" +msgstr "사용자 정의 연산자 클래스를 읽는 중" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator families" +msgstr "사용자 정의 연산자 부류들 읽는 중" + +#: common.c:174 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "사용자 정의 텍스트 검색 파서를 읽는 중" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search templates" +msgstr "사용자 정의 텍스트 검색 템플릿을 읽는 중" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "사용자 정의 텍스트 검색 사전을 읽는 중" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "사용자 정의 텍스트 검색 구성을 읽는 중" + +#: common.c:186 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "사용자 정의 외부 데이터 래퍼를 읽는 중" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "사용자 정의 외부 서버를 읽는 중" + +#: common.c:192 +#, c-format +msgid "reading default privileges" +msgstr "기본 접근 권한 읽는 중" + +#: common.c:195 +#, c-format +msgid "reading user-defined collations" +msgstr "사용자 정의 글자 정렬(collation) 읽는 중" + +#: common.c:199 +#, c-format +msgid "reading user-defined conversions" +msgstr "사용자 정의 인코딩 변환규칙을 읽는 중" + +#: common.c:202 +#, c-format +msgid "reading type casts" +msgstr "형변환자(type cast)들을 읽는 중" + +#: common.c:205 +#, c-format +msgid "reading transforms" +msgstr "변환자(transform) 읽는 중" + +#: common.c:208 +#, c-format +msgid "reading table inheritance information" +msgstr "테이블 상속 정보를 읽는 중" + +#: common.c:211 +#, c-format +msgid "reading event triggers" +msgstr "이벤트 트리거들을 읽는 중" + +#: common.c:215 +#, c-format +msgid "finding extension tables" +msgstr "확장 테이블을 찾는 중" + +#: common.c:219 +#, c-format +msgid "finding inheritance relationships" +msgstr "상속 관계를 조사중" + +#: common.c:222 +#, c-format +msgid "reading column info for interesting tables" +msgstr "재미난 테이블들(interesting tables)을 위해 열 정보를 읽는 중" + +#: common.c:225 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "하위 테이블에서 상속된 열 구분중" + +#: common.c:228 +#, c-format +msgid "reading indexes" +msgstr "인덱스들을 읽는 중" + +#: common.c:231 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "하위 파티션 테이블에서 인덱스를 플래그 처리하는 중" + +#: common.c:234 +#, c-format +msgid "reading extended statistics" +msgstr "확장 통계들을 읽는 중" + +#: common.c:237 +#, c-format +msgid "reading constraints" +msgstr "제약 조건들을 읽는 중" + +#: common.c:240 +#, c-format +msgid "reading triggers" +msgstr "트리거들을 읽는 중" + +#: common.c:243 +#, c-format +msgid "reading rewrite rules" +msgstr "룰(rule) 읽는 중" + +#: common.c:246 +#, c-format +msgid "reading policies" +msgstr "정책 읽는 중" + +#: common.c:249 +#, c-format +msgid "reading publications" +msgstr "발행 정보를 읽는 중" + +#: common.c:252 +#, c-format +msgid "reading publication membership" +msgstr "발행 맵버쉽을 읽을 중" + +#: common.c:255 +#, c-format +msgid "reading subscriptions" +msgstr "구독정보를 읽는 중" + +#: common.c:1025 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "안전 검사 실패, OID %u인 부모 개체가 없음. 해당 테이블 \"%s\" (OID %u)" + +#: common.c:1067 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "\"%s\" 숫자 배열을 분석할 수 없음: 너무 많은 숫자들이 있음" + +#: common.c:1082 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "\"%s\" 숫자 배열을 분석할 수 없음: 숫자안에 이상한 글자가 있음" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "잘못된 압축 수위: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "zlib 지원 기능이 없음" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "압축 라이브러리를 초기화 할 수 없음: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "압축 스트림을 닫을 수 없음: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "자료를 압축할 수 없음: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "자료 압축을 풀 수 없습니다: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "압축 라이브러리를 닫을 수 없음: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:557 pg_backup_tar.c:560 +#, c-format +msgid "could not read from input file: %s" +msgstr "입력 파일을 읽을 수 없음: %s" + +#: compress_io.c:623 pg_backup_custom.c:646 pg_backup_directory.c:552 +#: pg_backup_tar.c:793 pg_backup_tar.c:816 +#, c-format +msgid "could not read from input file: end of file" +msgstr "입력 파일을 읽을 수 없음: 파일 끝" + +# # search5 끝 +# # advance 부분 +#: parallel.c:267 +#, c-format +msgid "WSAStartup failed: %d" +msgstr "WSAStartup 작업 실패: %d" + +#: parallel.c:978 +#, c-format +msgid "could not create communication channels: %m" +msgstr "통신 체널을 만들 수 없음: %m" + +#: parallel.c:1035 +#, c-format +msgid "could not create worker process: %m" +msgstr "작업자 프로세스를 만들 수 없음: %m" + +#: parallel.c:1165 +#, c-format +msgid "unrecognized command received from master: \"%s\"" +msgstr "마스터에서 알 수 없는 명령을 받음: \"%s\"" + +#: parallel.c:1208 parallel.c:1446 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "작업 프로세스로부터 잘못된 메시지를 받음: \"%s\"" + +#: parallel.c:1340 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the " +"table after the pg_dump parent process had gotten the initial ACCESS SHARE " +"lock on the table." +msgstr "" +"\"%s\" 릴레이션을 선점할 수 없음\n" +"이 상황은 일반적으로 다른 세션에서 해당 테이블을 이미 덤프하고 있거나 기타 다" +"른 이유로 다른 세션에 의해서 선점 된 경우입니다." + +#: parallel.c:1429 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "작업 프로세스가 예상치 않게 종료됨" + +#: parallel.c:1551 parallel.c:1669 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "통신 체널에에 쓸 수 없음: %m" + +#: parallel.c:1628 +#, c-format +msgid "select() failed: %m" +msgstr "select() 실패: %m" + +#: parallel.c:1753 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: 소켓을 만들 수 없음: 오류 코드 %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: 바인딩 할 수 없음: 오류 코드 %d" + +#: parallel.c:1771 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: 리슨 할 수 없음: 오류 코드 %d" + +#: parallel.c:1778 +#, c-format +msgid "pgpipe: getsockname() failed: error code %d" +msgstr "pgpipe: getsockname() 실패: 오류 코드 %d" + +#: parallel.c:1789 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: 두번째 소켓을 만들 수 없음: 오류 코드 %d" + +#: parallel.c:1798 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: 소켓 접속 실패: 오류 코드 %d" + +#: parallel.c:1807 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: 접속을 승인할 수 없음: 오류 코드 %d" + +#: pg_backup_archiver.c:277 pg_backup_archiver.c:1587 +#, c-format +msgid "could not close output file: %m" +msgstr "출력 파일을 닫을 수 없음: %m" + +#: pg_backup_archiver.c:321 pg_backup_archiver.c:325 +#, c-format +msgid "archive items not in correct section order" +msgstr "아카이브 아이템의 순서가 섹션에서 비정상적임" + +#: pg_backup_archiver.c:331 +#, c-format +msgid "unexpected section code %d" +msgstr "예상치 못한 섹션 코드 %d" + +#: pg_backup_archiver.c:368 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "이 아카이브 파일 형식에서는 병렬 복원이 지원되지 않음" + +#: pg_backup_archiver.c:372 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "8.0 이전 pg_dump로 만든 아카이브에서는 병렬 복원이 지원되지 않음" + +#: pg_backup_archiver.c:390 +#, c-format +msgid "" +"cannot restore from compressed archive (compression not supported in this " +"installation)" +msgstr "" +"압축된 자료파일을 복원용으로 사용할 수 없습니다(압축기능을 지원하지 않고 컴파" +"일되었음)" + +#: pg_backup_archiver.c:407 +#, c-format +msgid "connecting to database for restore" +msgstr "복원 작업을 위해 데이터베이스에 접속 중" + +#: pg_backup_archiver.c:409 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "pre-1.3 archive에서 직통 데이터베이스 접속은 지원되지 않음" + +#: pg_backup_archiver.c:452 +#, c-format +msgid "implied data-only restore" +msgstr "암묵적으로 자료만 복원" + +#: pg_backup_archiver.c:518 +#, c-format +msgid "dropping %s %s" +msgstr "%s %s 삭제 중" + +#: pg_backup_archiver.c:613 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "\"%s\" 구문에서 insert IF EXISTS 부분을 찾을 수 없음" + +#: pg_backup_archiver.c:769 pg_backup_archiver.c:771 +#, c-format +msgid "warning from original dump file: %s" +msgstr "원본 덤프 파일에서 발생한 경고: %s" + +#: pg_backup_archiver.c:786 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "%s \"%s.%s\" 만드는 중" + +#: pg_backup_archiver.c:789 +#, c-format +msgid "creating %s \"%s\"" +msgstr "%s \"%s\" 만드는 중" + +#: pg_backup_archiver.c:839 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "\"%s\" 새 데이터베이스에 접속중" + +#: pg_backup_archiver.c:866 +#, c-format +msgid "processing %s" +msgstr "%s 처리 중" + +#: pg_backup_archiver.c:886 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블의 자료를 처리 중" + +#: pg_backup_archiver.c:948 +#, c-format +msgid "executing %s %s" +msgstr "실행중: %s %s" + +#: pg_backup_archiver.c:987 +#, c-format +msgid "disabling triggers for %s" +msgstr "%s 트리거 작동을 비활성화 하는 중" + +#: pg_backup_archiver.c:1013 +#, c-format +msgid "enabling triggers for %s" +msgstr "%s 트리거 작동을 활성화 하는 중" + +#: pg_backup_archiver.c:1041 +#, c-format +msgid "" +"internal error -- WriteData cannot be called outside the context of a " +"DataDumper routine" +msgstr "내부 오류 -- WriteData는 DataDumper 루틴 영역 밖에서 호출 될 수 없음" + +#: pg_backup_archiver.c:1224 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "선택한 파일 양식으로는 large-object를 덤프할 수 없음" + +#: pg_backup_archiver.c:1282 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "%d개의 큰 개체가 복원됨" + +#: pg_backup_archiver.c:1303 pg_backup_tar.c:736 +#, c-format +msgid "restoring large object with OID %u" +msgstr "%u OID large object를 복원중" + +#: pg_backup_archiver.c:1315 +#, c-format +msgid "could not create large object %u: %s" +msgstr "%u large object를 만들 수 없음: %s" + +#: pg_backup_archiver.c:1320 pg_dump.c:3548 +#, c-format +msgid "could not open large object %u: %s" +msgstr "%u large object를 열 수 없음: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "TOC 파일 \"%s\"을(를) 열 수 없음: %m" + +#: pg_backup_archiver.c:1417 +#, c-format +msgid "line ignored: %s" +msgstr "줄 무시됨: %s" + +#: pg_backup_archiver.c:1424 +#, c-format +msgid "could not find entry for ID %d" +msgstr "%d ID에 대한 항목을 찾지 못했음" + +#: pg_backup_archiver.c:1445 pg_backup_directory.c:222 +#: pg_backup_directory.c:598 +#, c-format +msgid "could not close TOC file: %m" +msgstr "TOC 파일을 닫을 수 없음: %m" + +#: pg_backup_archiver.c:1559 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:585 pg_backup_directory.c:648 +#: pg_backup_directory.c:667 pg_dumpall.c:484 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "\"%s\" 출력 파일을 열 수 없음: %m" + +#: pg_backup_archiver.c:1561 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "출력 파일을 열 수 없음: %m" + +#: pg_backup_archiver.c:1654 +#, c-format +msgid "wrote %lu byte of large object data (result = %lu)" +msgid_plural "wrote %lu bytes of large object data (result = %lu)" +msgstr[0] "%lu바이트의 큰 개체 데이터를 씀(결과 = %lu)" + +#: pg_backup_archiver.c:1659 +#, c-format +msgid "could not write to large object (result: %lu, expected: %lu)" +msgstr "large object를 쓸 수 없음 (결과값: %lu, 예상값: %lu)" + +#: pg_backup_archiver.c:1749 +#, c-format +msgid "while INITIALIZING:" +msgstr "초기화 작업 중:" + +#: pg_backup_archiver.c:1754 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "TOC 처리하는 중:" + +#: pg_backup_archiver.c:1759 +#, c-format +msgid "while FINALIZING:" +msgstr "뒷 마무리 작업 중:" + +#: pg_backup_archiver.c:1764 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "%d TOC 항목에서; %u %u %s %s %s" + +#: pg_backup_archiver.c:1840 +#, c-format +msgid "bad dumpId" +msgstr "잘못된 dumpID" + +#: pg_backup_archiver.c:1861 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "TABLE DATA 아이템에 대한 잘못된 테이블 dumpId" + +#: pg_backup_archiver.c:1953 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "예상치 못한 자료 옵셋 플래그 %d" + +#: pg_backup_archiver.c:1966 +#, c-format +msgid "file offset in dump file is too large" +msgstr "덤프 파일에서 파일 옵셋 값이 너무 큽니다" + +#: pg_backup_archiver.c:2103 pg_backup_archiver.c:2113 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "디렉터리 이름이 너무 긺: \"%s\"" + +#: pg_backup_archiver.c:2121 +#, c-format +msgid "" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not " +"exist)" +msgstr "\"%s\" 디렉터리가 알맞은 아카이브용이 아님 (\"toc.dat\" 파일이 없음)" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:173 pg_backup_custom.c:812 +#: pg_backup_directory.c:207 pg_backup_directory.c:394 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "\"%s\" 입력 파일을 열 수 없음: %m" + +#: pg_backup_archiver.c:2136 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "입력 파일을 열 수 없음: %m" + +#: pg_backup_archiver.c:2142 +#, c-format +msgid "could not read input file: %m" +msgstr "입력 파일을 읽을 수 없음: %m" + +#: pg_backup_archiver.c:2144 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "입력 파일이 너무 짧습니다 (%lu 읽었음, 예상치 5)" + +#: pg_backup_archiver.c:2229 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "입력 파일은 일반 텍스트 덤프 파일입니다. psql 명령을 사용하세요." + +#: pg_backup_archiver.c:2235 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "입력 파일에서 타당한 아카이브를 찾을 수 없습니다(너무 짧은지?)" + +#: pg_backup_archiver.c:2241 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "입력 파일에서 타당한 아카이브를 찾을 수 없음" + +#: pg_backup_archiver.c:2261 +#, c-format +msgid "could not close input file: %m" +msgstr "입력 파일을 닫을 수 없음: %m" + +#: pg_backup_archiver.c:2373 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "알 수 없는 파일 포멧: \"%d\"" + +#: pg_backup_archiver.c:2455 pg_backup_archiver.c:4458 +#, c-format +msgid "finished item %d %s %s" +msgstr "%d %s %s 항목 마침" + +#: pg_backup_archiver.c:2459 pg_backup_archiver.c:4471 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "작업자 프로세스 실패: 종료 코드 %d" + +#: pg_backup_archiver.c:2579 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "%d ID 항목은 범위를 벗어났음 -- TOC 정보가 손상된 듯 합니다" + +#: pg_backup_archiver.c:2646 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "WITH OIDS 옵션이 있는 테이블의 복원은 이제 지원하지 않습니다" + +#: pg_backup_archiver.c:2728 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "알 수 없는 인코딩: \"%s\"" + +#: pg_backup_archiver.c:2733 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "잘못된 ENCODING 항목: %s" + +#: pg_backup_archiver.c:2751 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "잘못된 STDSTRINGS 항목: %s" + +#: pg_backup_archiver.c:2776 +#, c-format +msgid "schema \"%s\" not found" +msgstr "\"%s\" 스키마를 찾을 수 없음" + +#: pg_backup_archiver.c:2783 +#, c-format +msgid "table \"%s\" not found" +msgstr "\"%s\" 테이블을 찾을 수 없음" + +#: pg_backup_archiver.c:2790 +#, c-format +msgid "index \"%s\" not found" +msgstr "\"%s\" 인덱스를 찾을 수 없음" + +#: pg_backup_archiver.c:2797 +#, c-format +msgid "function \"%s\" not found" +msgstr "\"%s\" 함수를 찾을 수 없음" + +#: pg_backup_archiver.c:2804 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "\"%s\" 트리거를 찾을 수 없음" + +#: pg_backup_archiver.c:3196 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "\"%s\" 사용자로 세션 사용자를 지정할 수 없음: %s" + +#: pg_backup_archiver.c:3328 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "search_path를 \"%s\"(으)로 지정할 수 없음: %s" + +#: pg_backup_archiver.c:3390 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "default_tablespace로 %s(으)로 지정할 수 없음: %s" + +#: pg_backup_archiver.c:3435 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "default_table_access_method를 지정할 수 없음: %s" + +#: pg_backup_archiver.c:3527 pg_backup_archiver.c:3685 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "\"%s\" 개체의 소유주를 지정할 수 없습니다" + +#: pg_backup_archiver.c:3789 +#, c-format +msgid "did not find magic string in file header" +msgstr "파일 헤더에서 매직 문자열을 찾지 못했습니다" + +#: pg_backup_archiver.c:3802 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "파일 헤더에 있는 %d.%d 버전은 지원되지 않습니다" + +#: pg_backup_archiver.c:3807 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "정수 크기 (%lu) 안전성 검사 실패" + +#: pg_backup_archiver.c:3811 +#, c-format +msgid "" +"archive was made on a machine with larger integers, some operations might " +"fail" +msgstr "" +"이 아카이브는 큰 정수를 지원하는 시스템에서 만들어졌습니다. 그래서 몇 동작이 " +"실패할 수도 있습니다." + +#: pg_backup_archiver.c:3821 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "예상되는 포멧 (%d)와 발견된 파일 포멧 (%d)이 서로 다름" + +#: pg_backup_archiver.c:3837 +#, c-format +msgid "" +"archive is compressed, but this installation does not support compression -- " +"no data will be available" +msgstr "" +"아카이브는 압축되어있지만, 이 프로그램에서는 압축기능을 지원하지 못합니다 -- " +"이 안에 있는 자료를 모두 사용할 수 없습니다." + +#: pg_backup_archiver.c:3855 +#, c-format +msgid "invalid creation date in header" +msgstr "헤더에 잘못된 생성 날짜가 있음" + +#: pg_backup_archiver.c:3983 +#, c-format +msgid "processing item %d %s %s" +msgstr "%d %s %s 항목을 처리하는 중" + +#: pg_backup_archiver.c:4062 +#, c-format +msgid "entering main parallel loop" +msgstr "기본 병렬 루프로 시작 중" + +#: pg_backup_archiver.c:4073 +#, c-format +msgid "skipping item %d %s %s" +msgstr "%d %s %s 항목을 건너뛰는 중" + +#: pg_backup_archiver.c:4082 +#, c-format +msgid "launching item %d %s %s" +msgstr "%d %s %s 항목을 시작하는 중" + +#: pg_backup_archiver.c:4136 +#, c-format +msgid "finished main parallel loop" +msgstr "기본 병렬 루프 마침" + +#: pg_backup_archiver.c:4172 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "누락된 %d %s %s 항목 처리 중" + +#: pg_backup_archiver.c:4777 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "\"%s\" 테이블을 만들 수 없어, 해당 자료는 복원되지 않을 것입니다." + +#: pg_backup_custom.c:378 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "잘못된 large object용 OID" + +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:632 +#: pg_backup_custom.c:870 pg_backup_tar.c:1086 pg_backup_tar.c:1091 +#, c-format +msgid "error during file seek: %m" +msgstr "파일 seek 작업하는 도중 오류가 발생했습니다: %m" + +#: pg_backup_custom.c:480 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "%d 자료 블록에 잘못된 접근 위치가 있음" + +#: pg_backup_custom.c:497 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "아카이브 검색하는 동안 알 수 없는 자료 블럭 형태(%d)를 발견함" + +#: pg_backup_custom.c:519 +#, c-format +msgid "" +"could not find block ID %d in archive -- possibly due to out-of-order " +"restore request, which cannot be handled due to non-seekable input file" +msgstr "" +"아카이브에서 블록 ID %d을(를) 찾지 못했습니다. 복원 요청이 잘못된 것 같습니" +"다. 입력 파일을 검색할 수 없으므로 요청을 처리할 수 없습니다." + +#: pg_backup_custom.c:524 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "" +"아카이브에서 블록 ID %d을(를) 찾을 수 없습니다. 아카이브가 손상된 것 같습니" +"다." + +#: pg_backup_custom.c:531 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "자료를 읽는 동안 예상치 못한 ID (%d) 발견됨 -- 예상값 %d" + +#: pg_backup_custom.c:545 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "아카이브 복원하는 중에, 알 수 없는 자료 블럭 형태 %d 를 발견함" + +#: pg_backup_custom.c:648 +#, c-format +msgid "could not read from input file: %m" +msgstr "입력 파일을 읽을 수 없음: %m" + +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:948 +#: pg_backup_tar.c:1089 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "아카이브 파일에서 검색 위치를 확인할 수 없음: %m" + +#: pg_backup_custom.c:767 pg_backup_custom.c:807 +#, c-format +msgid "could not close archive file: %m" +msgstr "자료 파일을 닫을 수 없음: %m" + +#: pg_backup_custom.c:790 +#, c-format +msgid "can only reopen input archives" +msgstr "입력 아카이브만 다시 열 수 있음" + +#: pg_backup_custom.c:797 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "표준 입력을 이용한 병렬 복원 작업은 지원하지 않습니다" + +#: pg_backup_custom.c:799 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "" +"시작 위치를 임의로 지정할 수 없는 파일로는 병렬 복원 작업을 할 수 없습니다." + +#: pg_backup_custom.c:815 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "아카이브 파일에서 검색 위치를 설정할 수 없음: %m" + +#: pg_backup_custom.c:894 +#, c-format +msgid "compressor active" +msgstr "압축기 사용" + +#: pg_backup_db.c:41 +#, c-format +msgid "could not get server_version from libpq" +msgstr "libpq에서 server_verion 값을 구할 수 없음" + +#: pg_backup_db.c:52 pg_dumpall.c:1826 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "서버 버전: %s; %s 버전: %s" + +#: pg_backup_db.c:54 pg_dumpall.c:1828 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "서버 버전이 일치하지 않아 중단하는 중" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "데이터베이스에 이미 접속해 있음" + +#: pg_backup_db.c:133 pg_backup_db.c:185 pg_dumpall.c:1651 pg_dumpall.c:1764 +msgid "Password: " +msgstr "암호: " + +#: pg_backup_db.c:177 +#, c-format +msgid "could not connect to database" +msgstr "데이터베이스 접속을 할 수 없음" + +#: pg_backup_db.c:195 +#, c-format +msgid "reconnection to database \"%s\" failed: %s" +msgstr "\"%s\" 데이터베이스 재접속 실패: %s" + +#: pg_backup_db.c:199 +#, c-format +msgid "connection to database \"%s\" failed: %s" +msgstr "\"%s\" 데이터베이스에 접속 할 수 없음: %s" + +#: pg_backup_db.c:272 pg_dumpall.c:1684 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:279 pg_dumpall.c:1889 pg_dumpall.c:1912 +#, c-format +msgid "query failed: %s" +msgstr "쿼리 실패: %s" + +#: pg_backup_db.c:281 pg_dumpall.c:1890 pg_dumpall.c:1913 +#, c-format +msgid "query was: %s" +msgstr "사용한 쿼리: %s" + +#: pg_backup_db.c:322 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "쿼리에서 한 개가 아닌 %d개의 행을 반환: %s" + +#: pg_backup_db.c:358 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %s사용된 명령: %s" + +#: pg_backup_db.c:414 pg_backup_db.c:488 pg_backup_db.c:495 +msgid "could not execute query" +msgstr "쿼리를 실행 할 수 없음" + +#: pg_backup_db.c:467 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "PQputCopyData에 의해서 오류가 반환되었음: %s" + +#: pg_backup_db.c:516 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "PQputCopyEnd에 의해서 오류가 반환되었음: %s" + +#: pg_backup_db.c:522 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "\"%s\" 테이블을 위한 COPY 실패: %s" + +#: pg_backup_db.c:528 pg_dump.c:1988 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "\"%s\" 테이블 COPY 작업 중 잘못된 부가 결과가 있음" + +#: pg_backup_db.c:540 +msgid "could not start database transaction" +msgstr "데이터베이스 트랜잭션을 시작할 수 없음" + +#: pg_backup_db.c:548 +msgid "could not commit database transaction" +msgstr "데이터베이스 트랜잭션을 commit 할 수 없음" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "자료가 저장될 디렉터리를 지정하지 않았음" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:496 +#: pg_backup_directory.c:532 +#, c-format +msgid "could not write to output file: %s" +msgstr "출력 파일을 쓸 수 없음: %s" + +#: pg_backup_directory.c:406 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "\"%s\" 자료 파일을 닫을 수 없음: %m" + +#: pg_backup_directory.c:446 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "입력용 large object TOC 파일(\"%s\")을 열 수 없음: %m" + +#: pg_backup_directory.c:457 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음: \"%s\"" + +#: pg_backup_directory.c:466 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음" + +#: pg_backup_directory.c:470 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음: %m" + +#: pg_backup_directory.c:689 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "blob TOC 파일에 쓸 수 없음" + +#: pg_backup_directory.c:721 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "파일 이름이 너무 긺: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "이 파일 형태는 읽을 수 없음" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "출력용 TOC 파일 \"%s\"을(를) 열 수 없음: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "출력용 TOC 파일을 열 수 없음: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:358 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "tar 출력 포멧에서 압축 기능을 지원하지 않음" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "입력용 TOC 파일(\"%s\")을 열 수 없음: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "입력용 TOC 파일을 열 수 없음: %m" + +#: pg_backup_tar.c:344 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "아카이브에서 \"%s\" 파일을 찾을 수 없음" + +#: pg_backup_tar.c:410 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "임시 파일 이름을 짓지 못했습니다: %m" + +#: pg_backup_tar.c:421 +#, c-format +msgid "could not open temporary file" +msgstr "임시 파일을 열 수 없음" + +#: pg_backup_tar.c:448 +#, c-format +msgid "could not close tar member" +msgstr "tar 맴버를 닫지 못했습니다" + +#: pg_backup_tar.c:691 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "COPY 구문 오류: \"%s\"" + +#: pg_backup_tar.c:958 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "잘못된 large object OID: %u" + +#: pg_backup_tar.c:1105 +#, c-format +msgid "could not close temporary file: %m" +msgstr "임시 파일을 열 수 없음: %m" + +#: pg_backup_tar.c:1114 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "실재 파일 길이(%s)와 예상되는 값(%s)이 다릅니다" + +#: pg_backup_tar.c:1171 pg_backup_tar.c:1201 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "tar 아카이브에서 \"%s\" 파일을 위한 헤더를 찾을 수 없음" + +#: pg_backup_tar.c:1189 +#, c-format +msgid "" +"restoring data out of order is not supported in this archive format: \"%s\" " +"is required, but comes before \"%s\" in the archive file." +msgstr "" +"순서를 넘어서는 자료 덤프 작업은 이 아카이브 포멧에서는 지원하지 않습니다: " +"\"%s\" 요구되었지만, 이 아카이브 파일에서는 \"%s\" 전에 옵니다." + +#: pg_backup_tar.c:1234 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "불완전한 tar 헤더가 있음(%lu 바이트)" + +#: pg_backup_tar.c:1285 +#, c-format +msgid "" +"corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "%s 안에 손상된 tar 헤더 발견 (예상치 %d, 계산된 값 %d), 파일 위치 %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "알 수 없는 섹션 이름: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:607 pg_dump.c:624 pg_dumpall.c:338 +#: pg_dumpall.c:348 pg_dumpall.c:357 pg_dumpall.c:366 pg_dumpall.c:374 +#: pg_dumpall.c:388 pg_dumpall.c:464 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "보다 자세한 사용법은 \"%s --help\"\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "on_exit_nicely 슬롯 범위 벗어남" + +#: pg_dump.c:533 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "압축 수위는 0부터 9까지 지정할 수 있음" + +#: pg_dump.c:571 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits 값은 -15..3 사이값이어야 함" + +#: pg_dump.c:594 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert 값은 %d부터 %d까지 지정할 수 있습니다." + +#: pg_dump.c:622 pg_dumpall.c:346 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "너무 많은 명령행 인자를 지정했음 (시작: \"%s\")" + +#: pg_dump.c:643 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "-s/--schema-only 옵션과 -a/--data-only 옵션은 함께 사용할 수 없음" + +#: pg_dump.c:648 +#, c-format +msgid "" +"options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "" +"-s/--schema-only 옵션과 --include-foreign-data 옵션은 함께 사용할 수 없음" + +#: pg_dump.c:651 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "--include-foreign-data 옵션은 병렬 백업 작업에서 지원하지 않음" + +#: pg_dump.c:655 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "-c/--clean 옵션과 -a/--data-only 옵션은 함께 사용할 수 없음" + +#: pg_dump.c:660 pg_dumpall.c:381 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "--if-exists 옵션은 -c/--clean 옵션과 함께 사용해야 함" + +#: pg_dump.c:667 +#, c-format +msgid "" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-" +"insert, or --column-inserts" +msgstr "" +"--on-conflict-do-nothing 옵션은 --inserts, --rows-per-insert 또는 --column-" +"inserts 옵션과 함께 사용해야 함" + +#: pg_dump.c:689 +#, c-format +msgid "" +"requested compression not available in this installation -- archive will be " +"uncompressed" +msgstr "" +"요청한 압축 기능은 이 설치판에서는 사용할 수 없습니다 -- 자료 파일은 압축 없" +"이 만들어질 것입니다" + +#: pg_dump.c:710 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "잘못된 병렬 작업 수" + +#: pg_dump.c:714 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "병렬 백업은 디렉터리 기반 출력일 때만 사용할 수 있습니다." + +#: pg_dump.c:769 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"이 서버 버전에서는 동기화된 스냅샷 기능을 사용할 수 없음.\n" +"동기화된 스냅샷 기능이 필요 없다면, --no-synchronized-snapshots\n" +"옵션을 지정해서 덤프할 수 있습니다." + +#: pg_dump.c:775 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "이 서버는 exported snapshot을 지원하지 않음." + +#: pg_dump.c:787 +#, c-format +msgid "last built-in OID is %u" +msgstr "마지막 내장 OID는 %u" + +#: pg_dump.c:796 +#, c-format +msgid "no matching schemas were found" +msgstr "조건에 맞는 스키마가 없습니다" + +#: pg_dump.c:810 +#, c-format +msgid "no matching tables were found" +msgstr "조건에 맞는 테이블이 없습니다" + +#: pg_dump.c:990 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s 프로그램은 데이터베이스를 텍스트 파일 또는 기타\n" +"다른 형태의 파일로 덤프합니다.\n" +"\n" + +#: pg_dump.c:991 pg_dumpall.c:617 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "사용법:\n" + +#: pg_dump.c:992 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [옵션]... [DB이름]\n" + +#: pg_dump.c:994 pg_dumpall.c:620 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"일반 옵션들:\n" + +#: pg_dump.c:995 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=파일이름 출력 파일 또는 디렉터리 이름\n" + +#: pg_dump.c:996 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p 출력 파일 형식(사용자 지정, 디렉터리, tar,\n" +" 일반 텍스트(초기값))\n" + +#: pg_dump.c:998 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=개수 덤프 작업을 병렬 처리 함\n" + +#: pg_dump.c:999 pg_dumpall.c:622 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 작업 내역을 자세히 봄\n" + +#: pg_dump.c:1000 pg_dumpall.c:623 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" + +#: pg_dump.c:1001 +#, c-format +msgid "" +" -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 출력 자료 압축 수위\n" + +#: pg_dump.c:1002 pg_dumpall.c:624 +#, c-format +msgid "" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr "" +" --lock-wait-timeout=초 테이블 잠금 시 지정한 초만큼 기다린 후 실패\n" + +#: pg_dump.c:1003 pg_dumpall.c:651 +#, c-format +msgid "" +" --no-sync do not wait for changes to be written safely " +"to disk\n" +msgstr " --no-sync fsync 작업 생략\n" + +#: pg_dump.c:1004 pg_dumpall.c:625 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" + +#: pg_dump.c:1006 pg_dumpall.c:626 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"출력 내용을 다루는 옵션들:\n" + +#: pg_dump.c:1007 pg_dumpall.c:627 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only 스키마 빼고 자료만 덤프\n" + +#: pg_dump.c:1008 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs Large Object들도 함께 덤프함\n" + +#: pg_dump.c:1009 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs Large Object들을 제외하고 덤프함\n" + +#: pg_dump.c:1010 pg_restore.c:476 +#, c-format +msgid "" +" -c, --clean clean (drop) database objects before " +"recreating\n" +msgstr "" +" -c, --clean 다시 만들기 전에 데이터베이스 개체 지우기(삭" +"제)\n" + +#: pg_dump.c:1011 +#, c-format +msgid "" +" -C, --create include commands to create database in dump\n" +msgstr "" +" -C, --create 데이터베이스 만드는 명령구문도 포함시킴\n" + +#: pg_dump.c:1012 pg_dumpall.c:629 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=인코딩 지정한 인코딩으로 자료를 덤프 함\n" + +#: pg_dump.c:1013 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATTERN 지정한 SCHEMA들 자료만 덤프\n" + +#: pg_dump.c:1014 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN 지정한 SCHEMA들만 빼고 모두 덤프\n" + +#: pg_dump.c:1015 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner 일반 텍스트 형식에서\n" +" 개체 소유권 복원 건너뛰기\n" + +#: pg_dump.c:1017 pg_dumpall.c:633 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only 자료구조(스키마)만 덤프\n" + +#: pg_dump.c:1018 +#, c-format +msgid "" +" -S, --superuser=NAME superuser user name to use in plain-text " +"format\n" +msgstr "" +" -S, --superuser=NAME 일반 텍스트 형식에서 사용할 슈퍼유저 사용자 이" +"름\n" + +#: pg_dump.c:1019 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATTERN 지정한 이름의 테이블들만 덤프\n" + +#: pg_dump.c:1020 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATTERN 지정한 테이블들만 빼고 덤프\n" + +#: pg_dump.c:1021 pg_dumpall.c:636 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr "" +" -x, --no-privileges 접근 권한 (grant/revoke) 정보는 덤프 안 함\n" + +#: pg_dump.c:1022 pg_dumpall.c:637 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade 업그레이드 유틸리티 전용\n" + +#: pg_dump.c:1023 pg_dumpall.c:638 +#, c-format +msgid "" +" --column-inserts dump data as INSERT commands with column " +"names\n" +msgstr "" +" --column-inserts 칼럼 이름과 함께 INSERT 명령으로 자료 덤프\n" + +#: pg_dump.c:1024 pg_dumpall.c:639 +#, c-format +msgid "" +" --disable-dollar-quoting disable dollar quoting, use SQL standard " +"quoting\n" +msgstr "" +" --disable-dollar-quoting $ 인용 구문 사용안함, SQL 표준 따옴표 사용\n" + +#: pg_dump.c:1025 pg_dumpall.c:640 pg_restore.c:493 +#, c-format +msgid "" +" --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers 자료만 복원할 때 트리거 사용을 안함\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user " +"has\n" +" access to)\n" +msgstr "" +" --enable-row-security 로우 보안 활성화 (현재 작업자가 접근할 수\n" +" 있는 자료만 덤프 함)\n" + +#: pg_dump.c:1028 +#, c-format +msgid "" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATTERN 해당 테이블 자료는 덤프 안함\n" + +#: pg_dump.c:1029 pg_dumpall.c:642 +#, c-format +msgid "" +" --extra-float-digits=NUM override default setting for " +"extra_float_digits\n" +msgstr " --extra-float-digits=NUM 기본 extra_float_digits 값 바꿈\n" + +#: pg_dump.c:1030 pg_dumpall.c:643 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists 객체 삭제 시 IF EXISTS 구문 사용\n" + +#: pg_dump.c:1031 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=패턴\n" +" 지정한 패턴과 일치하는 외부 서버의 외부\n" +" 테이블 자료를 포함\n" + +#: pg_dump.c:1034 pg_dumpall.c:644 +#, c-format +msgid "" +" --inserts dump data as INSERT commands, rather than " +"COPY\n" +msgstr " --inserts COPY 대신 INSERT 명령으로 자료 덤프\n" + +#: pg_dump.c:1035 pg_dumpall.c:645 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr "" +" --load-via-partition-root 상위 테이블을 통해 하위 테이블을 로드함\n" + +#: pg_dump.c:1036 pg_dumpall.c:646 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments 코멘트는 덤프 안함\n" + +#: pg_dump.c:1037 pg_dumpall.c:647 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications 발행 정보는 덤프하지 않음\n" + +#: pg_dump.c:1038 pg_dumpall.c:649 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels 보안 라벨 할당을 덤프 하지 않음\n" + +#: pg_dump.c:1039 pg_dumpall.c:650 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions 구독 정보는 덤프하지 않음\n" + +#: pg_dump.c:1040 +#, c-format +msgid "" +" --no-synchronized-snapshots do not use synchronized snapshots in parallel " +"jobs\n" +msgstr "" +" --no-synchronized-snapshots 병렬 작업에서 스냅샷 일관성을 맞추지 않음\n" + +#: pg_dump.c:1041 pg_dumpall.c:652 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces 테이블스페이스 할당을 덤프하지 않음\n" + +#: pg_dump.c:1042 pg_dumpall.c:653 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data 언로그드 테이블 자료는 덤프하지 않음\n" + +#: pg_dump.c:1043 pg_dumpall.c:654 +#, c-format +msgid "" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT " +"commands\n" +msgstr "" +" --on-conflict-do-nothing INSERT 구문에 ON CONFLICT DO NOTHING 옵션 추" +"가\n" + +#: pg_dump.c:1044 pg_dumpall.c:655 +#, c-format +msgid "" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers 예약어가 아니여도 모든 식별자는 따옴표를 씀\n" + +#: pg_dump.c:1045 pg_dumpall.c:656 +#, c-format +msgid "" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr "" +" --rows-per-insert=NROWS 한 INSERT 명령으로 입력할 로우 수; --inserts\n" +" 옵션을 사용한 것으로 가정 함\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" --section=SECTION dump named section (pre-data, data, or post-" +"data)\n" +msgstr "" +" --section=SECTION 해당 섹션(pre-data, data, post-data)만 덤프\n" + +#: pg_dump.c:1047 +#, c-format +msgid "" +" --serializable-deferrable wait until the dump can run without " +"anomalies\n" +msgstr "" +" --serializable-deferrable 자료 정합성을 보장하기 위해 덤프 작업을\n" +" 직렬화 가능한 트랜잭션으로 처리 함\n" + +#: pg_dump.c:1048 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT 지정한 스냅샷을 덤프 함\n" + +#: pg_dump.c:1049 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns " +"to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names 테이블이나 스키마를 지정했을 때 그 패턴에 맞" +"는\n" +" 객체가 적어도 하나 이상 있어야 함\n" + +#: pg_dump.c:1051 pg_dumpall.c:657 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands " +"instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" SET SESSION AUTHORIZATION 명령을 ALTER OWNER " +"명령\n" +" 대신 사용하여 소유권 설정\n" + +#: pg_dump.c:1055 pg_dumpall.c:661 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"연결 옵션들:\n" + +#: pg_dump.c:1056 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME 덤프할 데이터베이스\n" + +#: pg_dump.c:1057 pg_dumpall.c:663 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr "" +" -h, --host=HOSTNAME 접속할 데이터베이스 서버 또는 소켓 디렉터리\n" + +#: pg_dump.c:1058 pg_dumpall.c:665 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT 데이터베이스 서버의 포트 번호\n" + +#: pg_dump.c:1059 pg_dumpall.c:666 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NAME 연결할 데이터베이스 사용자\n" + +#: pg_dump.c:1060 pg_dumpall.c:667 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password 암호 프롬프트 표시 안 함\n" + +#: pg_dump.c:1061 pg_dumpall.c:668 pg_restore.c:515 +#, c-format +msgid "" +" -W, --password force password prompt (should happen " +"automatically)\n" +msgstr " -W, --password 암호 입력 프롬프트 보임(자동으로 처리함)\n" + +#: pg_dump.c:1062 pg_dumpall.c:669 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME 덤프 전에 SET ROLE 수행\n" + +#: pg_dump.c:1064 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"데이터베이스 이름을 지정하지 않았다면, PGDATABASE 환경변수값을\n" +"사용합니다.\n" +"\n" + +#: pg_dump.c:1066 pg_dumpall.c:673 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "문제점 보고 주소 <%s>\n" + +#: pg_dump.c:1067 pg_dumpall.c:674 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s 홈페이지: <%s>\n" + +#: pg_dump.c:1086 pg_dumpall.c:499 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "클라이언트 인코딩 값이 잘못되었습니다: \"%s\"" + +#: pg_dump.c:1232 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server " +"version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"이 서버 버전에서는 대기 서버에서 동기화된 스냅샷 기능을 사용할 수 없음.\n" +"동기화된 스냅샷 기능이 필요 없다면, --no-synchronized-snapshots\n" +"옵션을 지정해서 덤프할 수 있습니다." + +#: pg_dump.c:1301 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "\"%s\" 값은 잘못된 출력 파일 형태입니다." + +#: pg_dump.c:1339 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "\"%s\" 검색 조건에 만족하는 스키마가 없습니다" + +#: pg_dump.c:1386 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "\"%s\" 검색 조건에 만족하는 외부 서버가 없습니다" + +#: pg_dump.c:1449 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "\"%s\" 검색 조건에 만족하는 테이블이 없습니다" + +#: pg_dump.c:1862 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블의 내용 덤프 중" + +#: pg_dump.c:1969 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "\"%s\" 테이블 내용을 덤프하면서 오류 발생: PQgetCopyData() 실패." + +#: pg_dump.c:1970 pg_dump.c:1980 +#, c-format +msgid "Error message from server: %s" +msgstr "서버에서 보낸 오류 메시지: %s" + +#: pg_dump.c:1971 pg_dump.c:1981 +#, c-format +msgid "The command was: %s" +msgstr "사용된 명령: %s" + +#: pg_dump.c:1979 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "\"%s\" 테이블 내용을 덤프하면서 오류 발생: PQgetResult() 실패." + +#: pg_dump.c:2735 +#, c-format +msgid "saving database definition" +msgstr "데이터베이스 구성정보를 저장 중" + +#: pg_dump.c:3207 +#, c-format +msgid "saving encoding = %s" +msgstr "인코딩 = %s 저장 중" + +#: pg_dump.c:3232 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "standard_conforming_strings = %s 저장 중" + +#: pg_dump.c:3271 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "current_schemas() 결과를 분석할 수 없음" + +#: pg_dump.c:3290 +#, c-format +msgid "saving search_path = %s" +msgstr "search_path = %s 저장 중" + +#: pg_dump.c:3330 +#, c-format +msgid "reading large objects" +msgstr "large object 읽는 중" + +#: pg_dump.c:3512 +#, c-format +msgid "saving large objects" +msgstr "large object들을 저장 중" + +#: pg_dump.c:3558 +#, c-format +msgid "error reading large object %u: %s" +msgstr "%u large object 읽는 중 오류: %s" + +#: pg_dump.c:3610 +#, c-format +msgid "reading row security enabled for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블을 위한 로우 보안 활성화를 읽는 중" + +#: pg_dump.c:3641 +#, c-format +msgid "reading policies for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블을 위한 정책 읽는 중" + +#: pg_dump.c:3793 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "예상치 못한 정책 명령 형태: %c" + +#: pg_dump.c:3944 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "\"%s\" 구독의 소유주가 적당하지 않습니다." + +#: pg_dump.c:4089 +#, c-format +msgid "reading publication membership for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블을 위한 발행 맵버쉽을 읽는 중" + +#: pg_dump.c:4232 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "" +"현재 사용자가 슈퍼유저가 아니기 때문에 서브스크립션들은 덤프하지 못했음" + +#: pg_dump.c:4286 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "\"%s\" 구독의 소유주가 적당하지 않습니다." + +#: pg_dump.c:4330 +#, c-format +msgid "could not parse subpublications array" +msgstr "구독 배열을 분석할 수 없음" + +#: pg_dump.c:4652 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "%s %s 객체와 관련된 상위 확장 기능을 찾을 수 없음" + +#: pg_dump.c:4784 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "\"%s\" 스키마의 소유주가 바르지 않습니다" + +#: pg_dump.c:4807 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "OID %u 스키마 없음" + +#: pg_dump.c:5132 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "\"%s\" 자료형의 소유주가 적당하지 않습니다." + +#: pg_dump.c:5217 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "\"%s\" 연산자의 소유주가 적당하지 않습니다." + +#: pg_dump.c:5519 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "\"%s\" 연산자 클래스의 소유주가 적당하지 않습니다." + +#: pg_dump.c:5603 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "\"%s\" 연산자 부류의 소유주가 적당하지 않습니다." + +#: pg_dump.c:5772 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "\"%s\" 집계 함수의 소유주가 적당하지 않습니다." + +#: pg_dump.c:6032 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "\"%s\" 함수의 소유주가 적당하지 않습니다." + +#: pg_dump.c:6860 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "\"%s\" 테이블의 소유주가 적당하지 않습니다." + +#: pg_dump.c:6902 pg_dump.c:17380 +#, c-format +msgid "" +"failed sanity check, parent table with OID %u of sequence with OID %u not " +"found" +msgstr "의존성 검사 실패, 부모 테이블 OID %u 없음. 해당 시퀀스 개체 OID %u" + +#: pg_dump.c:7044 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블에서 사용하는 인덱스들을 읽는 중" + +#: pg_dump.c:7459 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블에서 사용하는 참조키 제약조건을 읽는 중" + +#: pg_dump.c:7740 +#, c-format +msgid "" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID " +"%u not found" +msgstr "의존성 검사 실패, 부모 테이블 OID %u 없음. 해당 pg_rewrite 개체 OID %u" + +#: pg_dump.c:7823 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블에서 사용하는 트리거들을 읽는 중" + +#: pg_dump.c:7956 +#, c-format +msgid "" +"query produced null referenced table name for foreign key trigger \"%s\" on " +"table \"%s\" (OID of table: %u)" +msgstr "" +"쿼리가 참조테이블 정보가 없는 \"%s\" 참조키 트리거를 \"%s\" (해당 OID: %u) 테" +"이블에서 만들었습니다." + +#: pg_dump.c:8511 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블의 칼럼과 자료형을 찾는 중" + +#: pg_dump.c:8647 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "\"%s\" 테이블에 매겨져 있는 열 번호가 잘못되었습니다" + +#: pg_dump.c:8684 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블에서 default 표현들 찾는 중" + +#: pg_dump.c:8706 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "적당하지 않는 adnum 값: %d, 해당 테이블 \"%s\"" + +#: pg_dump.c:8771 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "\"%s.%s\" 테이블에서 사용하는 체크 제약 조건을 찾는 중" + +#: pg_dump.c:8820 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "" +"%d개의 제약 조건이 \"%s\" 테이블에 있을 것으로 예상했으나 %d개를 찾음" + +#: pg_dump.c:8824 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(시스템 카탈로그가 손상되었는 것 같습니다)" + +#: pg_dump.c:10410 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "\"%s\" 자료형의 typtype가 잘못 되어 있음" + +#: pg_dump.c:11764 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "proargmodes 배열에 잘못된 값이 있음" + +#: pg_dump.c:12136 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "proallargtypes 배열을 분석할 수 없습니다" + +#: pg_dump.c:12152 +#, c-format +msgid "could not parse proargmodes array" +msgstr "proargmodes 배열을 분석할 수 없습니다" + +#: pg_dump.c:12166 +#, c-format +msgid "could not parse proargnames array" +msgstr "proargnames 배열을 분석할 수 없습니다" + +#: pg_dump.c:12177 +#, c-format +msgid "could not parse proconfig array" +msgstr "proconfig 배열을 구문 분석할 수 없음" + +#: pg_dump.c:12257 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "\"%s\" 함수의 provolatile 값이 잘못 되었습니다" + +#: pg_dump.c:12307 pg_dump.c:14365 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "\"%s\" 함수의 proparallel 값이 잘못 되었습니다" + +#: pg_dump.c:12446 pg_dump.c:12555 pg_dump.c:12562 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "%u OID 함수에 대한 함수 정의를 찾을 수 없음" + +#: pg_dump.c:12485 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "pg_cast.castfunc 또는 pg_cast.castmethod 필드에 잘못된 값이 있음" + +#: pg_dump.c:12488 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "pg_cast.castmethod 필드에 잘못된 값이 있음" + +#: pg_dump.c:12581 +#, c-format +msgid "" +"bogus transform definition, at least one of trffromsql and trftosql should " +"be nonzero" +msgstr "잘못된 전송 정의, trffromsql 또는 trftosql 중 하나는 비어 있으면 안됨" + +#: pg_dump.c:12598 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "pg_transform.trffromsql 필드에 잘못된 값이 있음" + +#: pg_dump.c:12619 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "pg_transform.trftosql 필드에 잘못된 값이 있음" + +#: pg_dump.c:12935 +#, c-format +msgid "could not find operator with OID %s" +msgstr "%s OID의 연산자를 찾을 수 없음" + +#: pg_dump.c:13003 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "\"%c\" 잘못된 자료형, 해당 접근 방법: \"%s\"" + +#: pg_dump.c:13757 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "알 수 없는 정렬규칙 제공자 이름: %s" + +#: pg_dump.c:14229 +#, c-format +msgid "" +"aggregate function %s could not be dumped correctly for this database " +"version; ignored" +msgstr "" +"%s 집계 함수는 이 데이터베이스 버전에서는 바르게 덤프되질 못했습니다; 무시함" + +#: pg_dump.c:14284 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "\"%s\" 집계 함수용 aggfinalmodify 값이 이상함" + +#: pg_dump.c:14340 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "\"%s\" 집계 함수용 aggmfinalmodify 값이 이상함" + +#: pg_dump.c:15062 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "기본 접근 권한에서 알 수 없는 객체형이 있음: %d" + +#: pg_dump.c:15080 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "기본 ACL 목록 (%s)을 분석할 수 없음" + +#: pg_dump.c:15165 +#, c-format +msgid "" +"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) " +"for object \"%s\" (%s)" +msgstr "" +"GRANT ACL 목록 초기값 (%s) 또는 REVOKE ACL 목록 초기값 (%s) 분석할 수 없음, " +"해당 객체: \"%s\" (%s)" + +#: pg_dump.c:15173 +#, c-format +msgid "" +"could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s" +"\" (%s)" +msgstr "" +"GRANT ACL 목록 (%s) 또는 REVOKE ACL 목록 (%s) 분석할 수 없음, 해당 객체: \"%s" +"\" (%s)" + +#: pg_dump.c:15688 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "\"%s\" 뷰 정의 정보가 없습니다." + +#: pg_dump.c:15691 +#, c-format +msgid "" +"query to obtain definition of view \"%s\" returned more than one definition" +msgstr "\"%s\" 뷰 정의 정보가 하나 이상 있습니다." + +#: pg_dump.c:15698 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "\"%s\" 뷰의 정의 내용이 비어있습니다." + +#: pg_dump.c:15780 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS 옵션은 더이상 지원하지 않음 (\"%s\" 테이블)" + +#: pg_dump.c:16260 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "잘못된 부모 수: %d, 해당 테이블 \"%s\"" + +#: pg_dump.c:16583 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "잘못된 열 번호 %d, 해당 테이블 \"%s\"" + +#: pg_dump.c:16868 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "\"%s\" 제약 조건을 위한 인덱스가 빠졌습니다" + +#: pg_dump.c:17093 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "알 수 없는 제약 조건 종류: %c" + +#: pg_dump.c:17225 pg_dump.c:17445 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "" +"query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "" +"\"%s\" 시퀀스의 데이터를 가져오기 위한 쿼리에서 %d개의 행 반환(1개 필요)" + +#: pg_dump.c:17259 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "알 수 없는 시퀀스 형태: %s" + +#: pg_dump.c:17543 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "기대되지 않은 tgtype 값: %d" + +#: pg_dump.c:17617 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "잘못된 인수 문자열 (%s), 해당 트리거 \"%s\", 사용되는 테이블 \"%s\"" + +#: pg_dump.c:17853 +#, c-format +msgid "" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows " +"returned" +msgstr "" +"\"%s\" 규칙(\"%s\" 테이블)을 가져오기 위한 쿼리 실패: 잘못된 행 수 반환" + +#: pg_dump.c:18015 +#, c-format +msgid "could not find referenced extension %u" +msgstr "%u 확장기능과 관련된 상위 확장 기능을 찾을 수 없음" + +#: pg_dump.c:18229 +#, c-format +msgid "reading dependency data" +msgstr "의존 관계 자료 읽는 중" + +#: pg_dump.c:18322 +#, c-format +msgid "no referencing object %u %u" +msgstr "%u %u 개체의 하위 관련 개체가 없음" + +#: pg_dump.c:18333 +#, c-format +msgid "no referenced object %u %u" +msgstr "%u %u 개체의 상위 관련 개체가 없음" + +#: pg_dump.c:18706 +#, c-format +msgid "could not parse reloptions array" +msgstr "reloptions 배열을 분석할 수 없음" + +#: pg_dump_sort.c:360 +#, c-format +msgid "invalid dumpId %d" +msgstr "잘못된 dumpId %d" + +#: pg_dump_sort.c:366 +#, c-format +msgid "invalid dependency %d" +msgstr "잘못된 의존성 %d" + +#: pg_dump_sort.c:599 +#, c-format +msgid "could not identify dependency loop" +msgstr "의존 관계를 식별 할 수 없음" + +#: pg_dump_sort.c:1170 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "다음 데이블 간 참조키가 서로 교차하고 있음:" + +#: pg_dump_sort.c:1174 pg_dump_sort.c:1194 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1175 +#, c-format +msgid "" +"You might not be able to restore the dump without using --disable-triggers " +"or temporarily dropping the constraints." +msgstr "" +"--disable-triggers 옵션으로 복원할 수 있습니다. 또는 임시로 제약 조건을 삭제" +"하고 복원하세요." + +#: pg_dump_sort.c:1176 +#, c-format +msgid "" +"Consider using a full dump instead of a --data-only dump to avoid this " +"problem." +msgstr "" +"이 문제를 피하려면, --data-only 덤프 대신에 모든 덤프를 사용하길 권합니다." + +#: pg_dump_sort.c:1188 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "다음 항목 간 의존 관계를 분석할 수 없음:" + +#: pg_dumpall.c:199 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"\"%s\" 프로그램이 %s 작업에서 필요로 하지만, \"%s\" 프로그램이\n" +"있는 같은 디렉터리에서 찾을 수 없습니다.\n" +"설치 상태를 살펴 보십시오." + +#: pg_dumpall.c:204 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"\"%s\" 프로그램이 \"%s\" 작업 때문에 찾았지만, \n" +"%s 버전과 같지 않습니다.\n" +"설치 상태를 살펴 보십시오." + +#: pg_dumpall.c:356 +#, c-format +msgid "" +"option --exclude-database cannot be used together with -g/--globals-only, -" +"r/--roles-only, or -t/--tablespaces-only" +msgstr "" +"--exclude-database 옵션은 -g/--globals-only, -r/--roles-only, 또는 -t/--" +"tablespaces-only 옵션과 함께 쓸 수 없음" + +#: pg_dumpall.c:365 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "-g/--globals-only 옵션과 -r/--roles-only 옵션은 함께 사용할 수 없음" + +#: pg_dumpall.c:373 +#, c-format +msgid "" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "" +"-g/--globals-only 옵션과 -t/--tablespaces-only 옵션은 함께 사용할 수 없음" + +#: pg_dumpall.c:387 +#, c-format +msgid "" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "" +"-r/--roles-only 옵션과 -t/--tablespaces-only 옵션은 함께 사용할 수 없음" + +#: pg_dumpall.c:448 pg_dumpall.c:1754 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "\"%s\" 데이터베이스에 접속할 수 없음" + +#: pg_dumpall.c:462 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"\"postgres\" 또는 \"template1\" 데이터베이스에 연결할 수 없습니다.\n" +"다른 데이터베이스를 지정하십시오." + +#: pg_dumpall.c:616 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s 프로그램은 PostgreSQL 데이터베이스 클러스터를 SQL 스크립트 파일로\n" +"추출하는 프로그램입니다.\n" +"\n" + +#: pg_dumpall.c:618 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [옵션]...\n" + +#: pg_dumpall.c:621 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=파일이름 출력 파일 이름\n" + +#: pg_dumpall.c:628 +#, c-format +msgid "" +" -c, --clean clean (drop) databases before recreating\n" +msgstr "" +" -c, --clean 다시 만들기 전에 데이터베이스 지우기(삭제)\n" + +#: pg_dumpall.c:630 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr "" +" -g, --globals-only 데이터베이스는 제외하고 글로벌 개체만 덤프\n" + +#: pg_dumpall.c:631 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner 개체 소유권 복원 건너뛰기\n" + +#: pg_dumpall.c:632 +#, c-format +msgid "" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only 데이터베이스나 테이블스페이스는 제외하고 역할" +"만 덤프\n" + +#: pg_dumpall.c:634 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME 덤프에 사용할 슈퍼유저 사용자 이름\n" + +#: pg_dumpall.c:635 +#, c-format +msgid "" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only 데이터베이스나 역할은 제외하고 테이블스페이스" +"만 덤프\n" + +#: pg_dumpall.c:641 +#, c-format +msgid "" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr "" +" --exclude-database=PATTERN 해당 PATTERN에 일치하는 데이터베이스 제외\n" + +#: pg_dumpall.c:648 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords 롤용 비밀번호를 덤프하지 않음\n" + +#: pg_dumpall.c:662 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=접속문자열 서버 접속 문자열\n" + +#: pg_dumpall.c:664 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME 대체용 기본 데이터베이스\n" + +#: pg_dumpall.c:671 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the " +"standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"-f/--file을 사용하지 않으면 SQL 스크립트가 표준\n" +"출력에 쓰여집니다.\n" +"\n" + +#: pg_dumpall.c:877 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "롤 이름이 \"pg_\"로 시작함, 무시함: (%s)" + +#: pg_dumpall.c:1278 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "테이블스페이스 용 ACL 목록 (%s)을 분석할 수 없음, 해당개체 \"%s\"" + +#: pg_dumpall.c:1495 +#, c-format +msgid "excluding database \"%s\"" +msgstr "\"%s\" 데이터베이스를 제외하는 중" + +#: pg_dumpall.c:1499 +#, c-format +msgid "dumping database \"%s\"" +msgstr "\"%s\" 데이터베이스 덤프 중" + +#: pg_dumpall.c:1531 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "\"%s\" 데이터베이스에서 pg_dump 작업 중에 오류가 발생, 끝냅니다." + +#: pg_dumpall.c:1540 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "\"%s\" 출력 파일을 다시 열 수 없음: %m" + +#: pg_dumpall.c:1584 +#, c-format +msgid "running \"%s\"" +msgstr "\"%s\" 가동중" + +#: pg_dumpall.c:1775 +#, c-format +msgid "could not connect to database \"%s\": %s" +msgstr "\"%s\" 데이터베이스에 접속할 수 없음: %s" + +#: pg_dumpall.c:1805 +#, c-format +msgid "could not get server version" +msgstr "서버 버전을 알 수 없음" + +#: pg_dumpall.c:1811 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "\"%s\" 서버 버전을 분석할 수 없음" + +#: pg_dumpall.c:1883 pg_dumpall.c:1906 +#, c-format +msgid "executing %s" +msgstr "실행중: %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "-d/--dbname 옵션 또는 -f/--file 옵션 중 하나를 지정해야 함" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "-d/--dbname 옵션과 -f/--file 옵션은 함께 사용할 수 없음" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "-C/--clean 옵션과 -1/--single-transaction 옵션은 함께 사용할 수 없음" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "병렬 작업 최대수는 %d 입니다." + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "--single-transaction 및 병렬 작업을 함께 지정할 수는 없음" + +#: pg_restore.c:408 +#, c-format +msgid "" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "" +"알 수 없는 아카이브 형식: \"%s\"; 사용할 수 있는 값: \"c\", \"d\", \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "복원작업에서의 오류들이 무시되었음: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s 프로그램은 pg_dump로 만들어진 자료파일로 PostgreSQL 데이터베이스에\n" +"그 자료를 일괄 입력합니다.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [옵션]... [파일]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME 접속할 데이터베이스 이름\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FILENAME 출력 파일 이름 (표준 출력: -)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t 백업 파일 형식 (지정하지 않으면 자동분석)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list 자료의 요약된 목차를 보여줌\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 자세한 정보 보여줌\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"리스토어 처리를 위한 옵션들:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only 스키마는 빼고 자료만 입력함\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create 작업 대상 데이터베이스를 만듦\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr "" +" -e, --exit-on-error 오류가 생기면 끝냄, 기본은 계속 진행함\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME 지정한 인덱스 만듦\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM 여러 병렬 작업을 사용하여 복원\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FILENAME 출력을 선택하고 해당 순서를 지정하기 위해\n" +" 이 파일의 목차 사용\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME 해당 스키마의 개체들만 복원함\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME 해당 스키마의 개체들은 복원 안함\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) 지정한 함수 만듦\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only 자료구조(스키마)만 만듦\n" + +#: pg_restore.c:488 +#, c-format +msgid "" +" -S, --superuser=NAME superuser user name to use for disabling " +"triggers\n" +msgstr "" +" -S, --superuser=NAME 트리거를 사용하지 않기 위해 사용할 슈퍼유저\n" +" 사용자 이름\n" + +#: pg_restore.c:489 +#, c-format +msgid "" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NAME 복원할 객체 이름 (테이블, 뷰, 기타)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAME 지정한 트리거 만듦\n" + +#: pg_restore.c:491 +#, c-format +msgid "" +" -x, --no-privileges skip restoration of access privileges (grant/" +"revoke)\n" +msgstr " -x, --no-privileges 접근 권한(grant/revoke) 지정 안함\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction 하나의 트랜잭션 작업으로 복원함\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security 로우 보안 활성화\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments 코멘트는 복원하지 않음\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not " +"be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables 만들 수 없는 테이블에 대해서는 자료를 덤프하" +"지 않음\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications 발행 정보는 복원 안함\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels 보안 라벨을 복원하지 않음\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions 구독 정보는 복원 안함\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces 테이블스페이스 할당을 복원하지 않음\n" + +#: pg_restore.c:503 +#, c-format +msgid "" +" --section=SECTION restore named section (pre-data, data, or " +"post-data)\n" +msgstr "" +" --section=SECTION 지정한 섹션만 복원함\n" +" 섹션 종류: pre-data, data, post-data\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME 복원 전에 SET ROLE 수행\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and " +"specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"-I, -n, -N, -P, -t, -T, --section 옵션은 그 대상이 되는 객체를 복수로 지정하" +"기\n" +"위해서 여러번 사용할 수 있습니다.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"사용할 입력 파일을 지정하지 않았다면, 표준 입력(stdin)을 사용합니다.\n" +"\n" diff --git a/src/bin/pg_dump/po/ru.po b/src/bin/pg_dump/po/ru.po new file mode 100644 index 0000000..f4d7fd5 --- /dev/null +++ b/src/bin/pg_dump/po/ru.po @@ -0,0 +1,3435 @@ +# Russian message translation file for pg_dump +# Copyright (C) 2001-2016 PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# Serguei A. Mokhov , 2001-2005. +# Oleg Bartunov , 2004. +# Sergey Burladyan , 2012. +# Dmitriy Olshevskiy , 2014. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022. +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL current)\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-05-07 06:06+0300\n" +"PO-Revision-Date: 2022-05-07 06:20+0300\n" +"Last-Translator: Alexander Lakhin \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "важно: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "ошибка: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "предупреждение: " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "не удалось определить текущий каталог: %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "неверный исполняемый файл \"%s\"" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "не удалось прочитать исполняемый файл \"%s\"" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "не удалось найти запускаемый файл \"%s\"" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "не удалось перейти в каталог \"%s\": %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "не удалось прочитать символическую ссылку \"%s\": %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "ошибка в %s(): %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "нехватка памяти" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "неисполняемая команда" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "команда не найдена" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "дочерний процесс завершился с кодом возврата %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "дочерний процесс прерван исключением 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "дочерний процесс завершён по сигналу %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "дочерний процесс завершился с нераспознанным состоянием %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "чтение расширений" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "выявление членов расширений" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "чтение схем" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "чтение пользовательских таблиц" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "чтение пользовательских функций" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "чтение пользовательских типов" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "чтение процедурных языков" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "чтение пользовательских агрегатных функций" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "чтение пользовательских операторов" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "чтение пользовательских методов доступа" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "чтение пользовательских классов операторов" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "чтение пользовательских семейств операторов" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "чтение пользовательских анализаторов текстового поиска" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "чтение пользовательских шаблонов текстового поиска" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "чтение пользовательских словарей текстового поиска" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "чтение пользовательских конфигураций текстового поиска" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "чтение пользовательских оболочек сторонних данных" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "чтение пользовательских сторонних серверов" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "чтение прав по умолчанию" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "чтение пользовательских правил сортировки" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "чтение пользовательских преобразований" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "чтение приведений типов" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "чтение преобразований" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "чтение информации о наследовании таблиц" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "чтение событийных триггеров" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "поиск таблиц расширений" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "поиск связей наследования" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "чтение информации о столбцах интересующих таблиц" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "пометка наследованных столбцов в подтаблицах" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "чтение индексов" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "пометка индексов в секционированных таблицах" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "чтение расширенной статистики" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "чтение ограничений" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "чтение триггеров" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "чтение правил перезаписи" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "чтение политик" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "чтение публикаций" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "чтение участников публикаций" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "чтение подписок" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "неверное число родителей (%d) для таблицы \"%s\"" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "" +"нарушение целостности: родительская таблица с OID %u для таблицы \"%s\" (OID " +"%u) не найдена" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "не удалось разобрать числовой массив \"%s\": слишком много чисел" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "не удалось разобрать числовой массив \"%s\": неверный символ в числе" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "неверный код сжатия: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "программа собрана без поддержки zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "не удалось инициализировать библиотеку сжатия: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "не удалось закрыть поток сжатых данных: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "не удалось сжать данные: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "не удалось распаковать данные: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "не удалось закрыть библиотеку сжатия: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "не удалось прочитать входной файл: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "не удалось прочитать входной файл: конец файла" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "ошибка в %s() (код ошибки: %d)" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "не удалось создать каналы межпроцессного взаимодействия: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "не удалось создать рабочий процесс: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "от ведущего процесса получена нераспознанная команда: \"%s\"" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "от рабочего процесса получено ошибочное сообщение: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the " +"table after the pg_dump parent process had gotten the initial ACCESS SHARE " +"lock on the table." +msgstr "" +"не удалось получить блокировку отношения \"%s\".\n" +"Обычно это означает, что кто-то запросил блокировку ACCESS EXCLUSIVE для " +"этой таблицы после того, как родительский процесс pg_dump получил для неё " +"начальную блокировку ACCESS SHARE." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "рабочий процесс неожиданно прервался" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "не удалось записать в канал взаимодействия: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: не удалось создать сокет (код ошибки: %d)" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: не удалось привязаться к сокету (код ошибки: %d)" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: не удалось начать приём (код ошибки: %d)" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: ошибка в %s() (код ошибки: %d)" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: не удалось создать второй сокет (код ошибки: %d)" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: не удалось подключить сокет (код ошибки: %d)" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: не удалось принять соединение (код ошибки: %d)" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "не удалось закрыть выходной файл: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "в последовательности элементов архива нарушен порядок разделов" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "неожиданный код раздела %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "" +"параллельное восстановление не поддерживается с выбранным форматом архивного " +"файла" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "" +"параллельное восстановление возможно только для архивов, созданных pg_dump " +"версии 8.0 и новее" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "" +"cannot restore from compressed archive (compression not supported in this " +"installation)" +msgstr "" +"восстановить данные из сжатого архива нельзя (установленная версия не " +"поддерживает сжатие)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "подключение к базе данных для восстановления" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "" +"прямые подключения к базе данных не поддерживаются в архивах до версии 1.3" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "подразумевается восстановление только данных" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "удаляется %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "не удалось определить, куда добавить IF EXISTS в оператор \"%s\"" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "предупреждение из исходного файла: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "создаётся %s \"%s.%s\"" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "создаётся %s \"%s\"" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "подключение к новой базе данных \"%s\"" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "обрабатывается %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "обрабатываются данные таблицы \"%s.%s\"" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "выполняется %s %s" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "отключаются триггеры таблицы %s" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "включаются триггеры таблицы %s" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "" +"internal error -- WriteData cannot be called outside the context of a " +"DataDumper routine" +msgstr "" +"внутренняя ошибка -- WriteData нельзя вызывать вне контекста процедуры " +"DataDumper" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "выбранный формат не поддерживает выгрузку больших объектов" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "восстановлен %d большой объект" +msgstr[1] "восстановлено %d больших объекта" +msgstr[2] "восстановлено %d больших объектов" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "восстановление большого объекта с OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "не удалось создать большой объект %u: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "не удалось открыть большой объект %u: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "не удалось открыть файл оглавления \"%s\": %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "строка проигнорирована: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "не найдена запись для ID %d" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "не удалось закрыть файл оглавления: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "не удалось открыть выходной файл \"%s\": %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "не удалось открыть выходной файл: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "записан %zu байт данных большого объекта (результат = %d)" +msgstr[1] "записано %zu байта данных большого объекта (результат = %d)" +msgstr[2] "записано %zu байт данных большого объекта (результат = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "не удалось записать данные в большой объект: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "при инициализации:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "при обработке оглавления:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "при завершении:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "из записи оглавления %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "неверный dumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "неверный dumpId таблицы в элементе TABLE DATA" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "неожиданный флаг смещения данных: %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "слишком большое смещение в файле выгрузки" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "слишком длинное имя каталога: \"%s\"" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not " +"exist)" +msgstr "каталог \"%s\" не похож на архивный (в нём отсутствует \"toc.dat\")" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "не удалось открыть входной файл \"%s\": %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "не удалось открыть входной файл: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "не удалось прочитать входной файл: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "входной файл слишком короткий (прочитано байт: %lu, ожидалось: 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "" +"входной файл, видимо, имеет текстовый формат. Загрузите его с помощью psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "входной файл не похож на архив (возможно, слишком мал?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "входной файл не похож на архив" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "не удалось закрыть входной файл: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "неопознанный формат файла: \"%d\"" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "закончен объект %d %s %s" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "рабочий процесс завершился с кодом возврата %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "ID записи %d вне диапазона - возможно повреждено оглавление" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "восстановление таблиц со свойством WITH OIDS больше не поддерживается" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "нераспознанная кодировка \"%s\"" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "неверный элемент ENCODING: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "неверный элемент STDSTRINGS: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "схема \"%s\" не найдена" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "таблица \"%s\" не найдена" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "индекс \"%s\" не найден" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "функция \"%s\" не найдена" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "триггер \"%s\" не найден" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "не удалось переключить пользователя сессии на \"%s\": %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "не удалось присвоить search_path значение \"%s\": %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "не удалось задать для default_tablespace значение %s: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "не удалось задать default_table_access_method: %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "неизвестно, как назначить владельца для объекта типа \"%s\"" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "в заголовке файла не найдена нужная сигнатура" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "неподдерживаемая версия (%d.%d) в заголовке файла" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "несоответствие размера integer (%lu)" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "" +"archive was made on a machine with larger integers, some operations might " +"fail" +msgstr "" +"архив был сделан на компьютере большей разрядности -- возможен сбой " +"некоторых операций" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "ожидаемый формат (%d) отличается от формата, указанного в файле (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "" +"archive is compressed, but this installation does not support compression -- " +"no data will be available" +msgstr "" +"архив сжат, но установленная версия не поддерживает сжатие -- данные " +"недоступны" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "неверная дата создания в заголовке" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "обработка объекта %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "вход в основной параллельный цикл" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "объект %d %s %s пропускается" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "объект %d %s %s запускается" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "основной параллельный цикл закончен" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "обработка пропущенного объекта %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "создать таблицу \"%s\" не удалось, её данные не будут восстановлены" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "неверный OID большого объекта" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "ошибка при перемещении в файле: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "в блоке данных %d задана неверная позиция" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "нераспознанный тип блока данных (%d) при поиске архива" + +#: pg_backup_custom.c:517 +#, c-format +msgid "" +"could not find block ID %d in archive -- possibly due to out-of-order " +"restore request, which cannot be handled due to non-seekable input file" +msgstr "" +"не удалось найти в архиве блок с ID %d -- возможно, по причине не " +"последовательного запроса восстановления, который нельзя обработать с " +"файлом, не допускающим произвольный доступ" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "не удалось найти в архиве блок с ID %d -- возможно, архив испорчен" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "при чтении данных получен неожиданный ID блока (%d) -- ожидался: %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "нераспознанный тип блока данных %d при восстановлении архива" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "не удалось прочитать входной файл: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "не удалось определить позицию в файле архива: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "не удалось закрыть файл архива: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "повторно открыть можно только входные файлы" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "параллельное восстановление из стандартного ввода не поддерживается" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "" +"параллельное восстановление возможно только с файлом произвольного доступа" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "не удалось задать текущую позицию в файле архива: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "сжатие активно" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "не удалось получить версию сервера из libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "версия сервера: %s; версия %s: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "продолжение работы с другой версией сервера невозможно" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "подключение к базе данных уже установлено" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Пароль: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "не удалось переподключиться к базе" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "переподключиться не удалось: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "ошибка при выполнении запроса: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "запрос: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "запрос вернул %d строку вместо одной: %s" +msgstr[1] "запрос вернул %d строки вместо одной: %s" +msgstr[2] "запрос вернул %d строк вместо одной: %s" + +# skip-rule: language-mix +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sВыполнялась команда: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "не удалось выполнить запрос" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "ошибка в PQputCopyData: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "ошибка в PQputCopyEnd: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "сбой команды COPY для таблицы \"%s\": %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "неожиданные лишние результаты получены при COPY для таблицы \"%s\"" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "не удаётся начать транзакцию" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "не удалось зафиксировать транзакцию" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "выходной каталог не указан" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "не удалось закрыть каталог \"%s\": %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не удалось создать каталог \"%s\": %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "не удалось записать в выходной файл: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "не удалось закрыть файл данных: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "не удалось закрыть файл данных \"%s\": %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "" +"не удалось открыть для чтения файл оглавления больших объектов \"%s\": %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "неверная строка в файле оглавления больших объектов \"%s\": \"%s\"" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "ошибка чтения файла оглавления больших объектов \"%s\"" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "не удалось закрыть файл оглавления больших объектов \"%s\": %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "не удалось закрыть файл данных BLOB: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "не удалось записать в файл оглавления больших объектов" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "не удалось закрыть файл оглавления BLOB: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "слишком длинное имя файла: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "этот формат нельзя прочитать" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "не удалось открыть для записи файл оглавления \"%s\": %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "не удалось открыть для записи файл оглавления: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "формат архива tar не поддерживает сжатие" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "не удалось открыть для чтения файл оглавления \"%s\": %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "не удалось открыть для чтения файл оглавления: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "не удалось найти файл \"%s\" в архиве" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "не удалось получить имя для временного файла: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "не удалось открыть временный файл" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "не удалось закрыть компонент tar-архива: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "недопустимый синтаксис оператора COPY: \"%s\"" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "неверный OID для большого объекта (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "не удалось закрыть временный файл: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "действительная длина файла (%s) не равна ожидаемой (%s)" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "в архиве tar не найден заголовок для файла \"%s\"" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "" +"restoring data out of order is not supported in this archive format: \"%s\" " +"is required, but comes before \"%s\" in the archive file." +msgstr "" +"непоследовательное восстановление данных для данного формата архива не " +"поддерживается: требуется компонент \"%s\", но в файле архива прежде идёт " +"\"%s\"." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "найден неполный заголовок tar (размер %lu байт)" +msgstr[1] "найден неполный заголовок tar (размер %lu байта)" +msgstr[2] "найден неполный заголовок tar (размер %lu байт)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "" +"corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "" +"заголовок tar в %s повреждён (ожидалось: %d, получено: %d), позиция в файле: " +"%s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "нераспознанное имя раздела: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Для дополнительной информации попробуйте \"%s --help\".\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "превышен предел обработчиков штатного выхода" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "уровень сжатия должен быть в диапазоне 0..9" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "значение extra_float_digits должно быть в диапазоне -15..3" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "значение rows-per-insert должно быть в диапазоне %d..%d" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "слишком много аргументов командной строки (первый: \"%s\")" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "параметры -s/--schema-only и -a/--data-only исключают друг друга" + +#: pg_dump.c:666 +#, c-format +msgid "" +"options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "" +"параметры -s/--schema-only и --include-foreign-data исключают друг друга" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "" +"параметр --include-foreign-data не поддерживается при копировании в " +"параллельном режиме" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "параметры -c/--clean и -a/--data-only исключают друг друга" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "параметр --if-exists требует указания -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-" +"insert, or --column-inserts" +msgstr "" +"параметр --on-conflict-do-nothing требует указания --inserts, --rows-per-" +"insert или --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "" +"requested compression not available in this installation -- archive will be " +"uncompressed" +msgstr "" +"установленная версия программы не поддерживает сжатие -- архив не будет " +"сжиматься" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "неверное число параллельных заданий" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "" +"параллельное резервное копирование поддерживается только с форматом \"каталог" +"\"" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"В этой версии сервера синхронизированные снимки не поддерживаются.\n" +"Если они вам не нужны, укажите при запуске ключ\n" +"--no-synchronized-snapshots." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Экспортированные снимки не поддерживаются этой версией сервера." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "последний системный OID: %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "соответствующие схемы не найдены" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "соответствующие таблицы не найдены" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "соответствующие расширения не найдены" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s сохраняет резервную копию БД в текстовом файле или другом виде.\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Использование:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [ПАРАМЕТР]... [ИМЯ_БД]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Общие параметры:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=ИМЯ имя выходного файла или каталога\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p формат выводимых данных\n" +" (пользовательский | каталог | tar |\n" +" текстовый (по умолчанию))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr "" +" -j, --jobs=ЧИСЛО распараллелить копирование на указанное " +"число\n" +" заданий\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose режим подробных сообщений\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_dump.c:1031 +#, c-format +msgid "" +" -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 уровень сжатия при архивации\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid "" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr "" +" --lock-wait-timeout=ТАЙМ-АУТ прервать операцию при тайм-ауте блокировки " +"таблицы\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid "" +" --no-sync do not wait for changes to be written safely " +"to disk\n" +msgstr "" +" --no-sync не ждать надёжного сохранения изменений на " +"диске\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Параметры, управляющие выводом:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only выгрузить только данные, без схемы\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs выгрузить также большие объекты\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs исключить из выгрузки большие объекты\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid "" +" -c, --clean clean (drop) database objects before " +"recreating\n" +msgstr "" +" -c, --clean очистить (удалить) объекты БД при " +"восстановлении\n" + +#: pg_dump.c:1041 +#, c-format +msgid "" +" -C, --create include commands to create database in dump\n" +msgstr "" +" -C, --create добавить в копию команды создания базы " +"данных\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr "" +" -e, --extension=ШАБЛОН выгрузить только указанное расширение(я)\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=КОДИРОВКА выгружать данные в заданной кодировке\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=ШАБЛОН выгрузить только указанную схему(ы)\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=ШАБЛОН НЕ выгружать указанную схему(ы)\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner не восстанавливать владение объектами\n" +" при использовании текстового формата\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only выгрузить только схему, без данных\n" + +#: pg_dump.c:1049 +#, c-format +msgid "" +" -S, --superuser=NAME superuser user name to use in plain-text " +"format\n" +msgstr "" +" -S, --superuser=ИМЯ имя пользователя, который будет задействован\n" +" при восстановлении из текстового формата\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=ШАБЛОН выгрузить только указанную таблицу(ы)\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=ШАБЛОН НЕ выгружать указанную таблицу(ы)\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges не выгружать права (назначение/отзыв)\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade только для утилит обновления БД\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid "" +" --column-inserts dump data as INSERT commands with column " +"names\n" +msgstr "" +" --column-inserts выгружать данные в виде INSERT с именами " +"столбцов\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid "" +" --disable-dollar-quoting disable dollar quoting, use SQL standard " +"quoting\n" +msgstr "" +" --disable-dollar-quoting отключить спецстроки с $, выводить строки\n" +" по стандарту SQL\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid "" +" --disable-triggers disable triggers during data-only restore\n" +msgstr "" +" --disable-triggers отключить триггеры при восстановлении\n" +" только данных, без схемы\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user " +"has\n" +" access to)\n" +msgstr "" +" --enable-row-security включить защиту на уровне строк (выгружать " +"только\n" +" те данные, которые доступны пользователю)\n" + +#: pg_dump.c:1059 +#, c-format +msgid "" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr "" +" --exclude-table-data=ШАБЛОН НЕ выгружать данные указанной таблицы " +"(таблиц)\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid "" +" --extra-float-digits=NUM override default setting for " +"extra_float_digits\n" +msgstr "" +" --extra-float-digits=ЧИСЛО переопределить значение extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr "" +" --if-exists применять IF EXISTS при удалении объектов\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=ШАБЛОН\n" +" включать в копию данные сторонних таблиц с\n" +" серверов с именами, подпадающими под ШАБЛОН\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid "" +" --inserts dump data as INSERT commands, rather than " +"COPY\n" +msgstr "" +" --inserts выгрузить данные в виде команд INSERT, не " +"COPY\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr "" +" --load-via-partition-root загружать секции через главную таблицу\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments не выгружать комментарии\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications не выгружать публикации\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr "" +" --no-security-labels не выгружать назначения меток безопасности\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions не выгружать подписки\n" + +#: pg_dump.c:1071 +#, c-format +msgid "" +" --no-synchronized-snapshots do not use synchronized snapshots in parallel " +"jobs\n" +msgstr "" +" --no-synchronized-snapshots не использовать синхронизированные снимки\n" +" в параллельных заданиях\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr "" +" --no-tablespaces не выгружать назначения табличных " +"пространств\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression не выгружать методы сжатия TOAST\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr "" +" --no-unlogged-table-data не выгружать данные нежурналируемых таблиц\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid "" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT " +"commands\n" +msgstr "" +" --on-conflict-do-nothing добавлять ON CONFLICT DO NOTHING в команды " +"INSERT\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid "" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr "" +" --quote-all-identifiers заключать в кавычки все идентификаторы,\n" +" а не только ключевые слова\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid "" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr "" +" --rows-per-insert=ЧИСЛО число строк в одном INSERT; подразумевает --" +"inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid "" +" --section=SECTION dump named section (pre-data, data, or post-" +"data)\n" +msgstr "" +" --section=РАЗДЕЛ выгрузить заданный раздел\n" +" (pre-data, data или post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid "" +" --serializable-deferrable wait until the dump can run without " +"anomalies\n" +msgstr "" +" --serializable-deferrable дождаться момента для выгрузки данных без " +"аномалий\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr "" +" --snapshot=СНИМОК использовать при выгрузке заданный снимок\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns " +"to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names требовать, чтобы при указании шаблона " +"включения\n" +" таблицы и/или схемы ему соответствовал " +"минимум\n" +" один объект\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands " +"instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" устанавливать владельца, используя команды\n" +" SET SESSION AUTHORIZATION вместо ALTER OWNER\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Параметры подключения:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=БД имя базы данных для выгрузки\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr "" +" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=ПОРТ номер порта сервера БД\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=ИМЯ имя пользователя баз данных\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password не запрашивать пароль\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid "" +" -W, --password force password prompt (should happen " +"automatically)\n" +msgstr "" +" -W, --password запрашивать пароль всегда (обычно не требуется)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ИМЯ_РОЛИ выполнить SET ROLE перед выгрузкой\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Если имя базы данных не указано, используется переменная окружения " +"PGDATABASE.\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Об ошибках сообщайте по адресу <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашняя страница %s: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "указана неверная клиентская кодировка \"%s\"" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server " +"version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"В этой версии сервера синхронизированные снимки на ведомых серверах не " +"поддерживаются.\n" +"Если они вам не нужны, укажите при запуске ключ\n" +"--no-synchronized-snapshots." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "указан неверный формат вывода: \"%s\"" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "неверное полное имя (слишком много компонентов): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "схемы, соответствующие шаблону \"%s\", не найдены" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "расширения, соответствующие шаблону \"%s\", не найдены" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "сторонние серверы, соответствующие шаблону \"%s\", не найдены" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "неверное имя отношения (слишком много компонентов): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "таблицы, соответствующие шаблону \"%s\", не найдены" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "В данный момент вы не подключены к базе данных." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "ссылки между базами не реализованы: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "выгрузка содержимого таблицы \"%s.%s\"" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Ошибка выгрузки таблицы \"%s\": сбой в PQgetCopyData()." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Сообщение об ошибке с сервера: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "Выполнялась команда: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Ошибка выгрузки таблицы \"%s\": сбой в PQgetResult()." + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "из таблицы \"%s\" получено неверное количество полей" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "сохранение определения базы данных" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "сохранение кодировки (%s)" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "сохранение standard_conforming_strings (%s)" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "не удалось разобрать результат current_schemas()" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "сохранение search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "чтение больших объектов" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "сохранение больших объектов" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "ошибка чтения большого объекта %u: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "чтение политик защиты на уровне строк" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "нераспознанный тип команды в политике: %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "у публикации \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "" +"подписки не выгружены, так как текущий пользователь не суперпользователь" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "у подписки \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "не удалось разобрать массив subpublications" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "не удалось найти родительское расширение для %s %s" + +# TO REVIEW +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "у схемы \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "схема с OID %u не существует" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "у типа данных \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "у оператора \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "у класса операторов \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "у семейства операторов \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "у агрегатной функции \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "у функции \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "у таблицы \"%s\" по-видимому неправильный владелец" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "" +"failed sanity check, parent table with OID %u of sequence with OID %u not " +"found" +msgstr "" +"нарушение целостности: по OID %u не удалось найти родительскую таблицу " +"последовательности с OID %u" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "чтение индексов таблицы \"%s.%s\"" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "чтение ограничений внешних ключей таблицы \"%s.%s\"" + +#: pg_dump.c:7963 +#, c-format +msgid "" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID " +"%u not found" +msgstr "" +"нарушение целостности: по OID %u не удалось найти родительскую таблицу для " +"записи pg_rewrite с OID %u" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "чтение триггеров таблицы \"%s.%s\"" + +#: pg_dump.c:8229 +#, c-format +msgid "" +"query produced null referenced table name for foreign key trigger \"%s\" on " +"table \"%s\" (OID of table: %u)" +msgstr "" +"запрос выдал NULL вместо имени целевой таблицы для триггера внешнего ключа " +"\"%s\" в таблице \"%s\" (OID целевой таблицы: %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "поиск столбцов и типов таблицы \"%s.%s\"" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "неверная нумерация столбцов в таблице \"%s\"" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "поиск выражений по умолчанию для таблицы \"%s.%s\"" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "неверное значение adnum (%d) в таблице \"%s\"" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "поиск ограничений-проверок для таблицы \"%s.%s\"" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "" +"ожидалось %d ограничение-проверка для таблицы \"%s\", но найдено: %d" +msgstr[1] "" +"ожидалось %d ограничения-проверки для таблицы \"%s\", но найдено: %d" +msgstr[2] "" +"ожидалось %d ограничений-проверок для таблицы \"%s\", но найдено: %d" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Возможно, повреждены системные каталоги.)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "у типа данных \"%s\" по-видимому неправильный тип типа" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "неприемлемое значение в массиве proargmodes" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "не удалось разобрать массив proallargtypes" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "не удалось разобрать массив proargmodes" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "не удалось разобрать массив proargnames" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "не удалось разобрать массив proconfig" + +# TO REVEIW +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "недопустимое значение provolatile для функции \"%s\"" + +# TO REVEIW +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "недопустимое значение proparallel для функции \"%s\"" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "не удалось найти определение функции для функции с OID %u" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "неприемлемое значение в поле pg_cast.castfunc или pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "неприемлемое значение в поле pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "" +"bogus transform definition, at least one of trffromsql and trftosql should " +"be nonzero" +msgstr "" +"неприемлемое определение преобразования (trffromsql или trftosql должно быть " +"ненулевым)" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "неприемлемое значение в поле pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "неприемлемое значение в поле pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "постфиксные операторы больше не поддерживаются (оператор \"%s\")" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "оператор с OID %s не найден" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "неверный тип \"%c\" метода доступа \"%s\"" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "нераспознанный провайдер правил сортировки: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "нераспознанное значение aggfinalmodify для агрегата \"%s\"" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "нераспознанное значение aggmfinalmodify для агрегата \"%s\"" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "нераспознанный тип объекта в определении прав по умолчанию: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "не удалось разобрать список прав по умолчанию (%s)" + +#: pg_dump.c:15269 +#, c-format +msgid "" +"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) " +"for object \"%s\" (%s)" +msgstr "" +"не удалось разобрать изначальный список GRANT ACL (%s) или изначальный " +"список REVOKE ACL (%s) для объекта \"%s\" (%s)" + +#: pg_dump.c:15277 +#, c-format +msgid "" +"could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s" +"\" (%s)" +msgstr "" +"не удалось разобрать список GRANT ACL (%s) или список REVOKE ACL (%s) для " +"объекта \"%s\" (%s)" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "" +"запрос на получение определения представления \"%s\" не возвратил данные" + +#: pg_dump.c:15795 +#, c-format +msgid "" +"query to obtain definition of view \"%s\" returned more than one definition" +msgstr "" +"запрос на получение определения представления \"%s\" возвратил несколько " +"определений" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "определение представления \"%s\" пустое (длина равна нулю)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "свойство WITH OIDS больше не поддерживается (таблица \"%s\")" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "неверный номер столбца %d для таблицы \"%s\"" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "не удалось разобрать столбцы статистики в индексе" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "не удалось разобрать значения статистики в индексе" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "" +"столбцы, задающие статистику индекса, не соответствуют значениям по " +"количеству" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "отсутствует индекс для ограничения \"%s\"" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "нераспознанный тип ограничения: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "" +"query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "" +"запрос на получение данных последовательности \"%s\" вернул %d строку " +"(ожидалась 1)" +msgstr[1] "" +"запрос на получение данных последовательности \"%s\" вернул %d строки " +"(ожидалась 1)" +msgstr[2] "" +"запрос на получение данных последовательности \"%s\" вернул %d строк " +"(ожидалась 1)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "нераспознанный тип последовательности: %s" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "неожиданное значение tgtype: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "неверная строка аргументов (%s) для триггера \"%s\" таблицы \"%s\"" + +#: pg_dump.c:18070 +#, c-format +msgid "" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows " +"returned" +msgstr "" +"запрос на получение правила \"%s\" для таблицы \"%s\" возвратил неверное " +"число строк" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "не удалось найти упомянутое расширение %u" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "не удалось разобрать массив конфигураций расширения" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "не удалось разобрать массив условий расширения" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "конфигурации расширения не соответствуют условиям по количеству" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "чтение информации о зависимостях" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "нет подчинённого объекта %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "нет вышестоящего объекта %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "не удалось разобрать массив reloptions" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "неверный dumpId %d" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "неверная зависимость %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "не удалось определить цикл зависимостей" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "в следующей таблице зациклены ограничения внешних ключей:" +msgstr[1] "в следующих таблицах зациклены ограничения внешних ключей:" +msgstr[2] "в следующих таблицах зациклены ограничения внешних ключей:" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "" +"You might not be able to restore the dump without using --disable-triggers " +"or temporarily dropping the constraints." +msgstr "" +"Возможно, для восстановления базы потребуется использовать --disable-" +"triggers или временно удалить ограничения." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "" +"Consider using a full dump instead of a --data-only dump to avoid this " +"problem." +msgstr "" +"Во избежание этой проблемы, вероятно, стоит выгружать всю базу данных, а не " +"только данные (--data-only)." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "не удалось разрешить цикл зависимостей для следующих объектов:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Программа \"%s\" нужна для %s, но она не найдена\n" +"в каталоге \"%s\".\n" +"Проверьте правильность установки СУБД." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Программа \"%s\" найдена программой \"%s\",\n" +"но её версия отличается от версии %s.\n" +"Проверьте правильность установки СУБД." + +#: pg_dumpall.c:359 +#, c-format +msgid "" +"option --exclude-database cannot be used together with -g/--globals-only, -" +"r/--roles-only, or -t/--tablespaces-only" +msgstr "" +"параметр --exclude-database несовместим с -g/--globals-only, -r/--roles-only " +"и -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "параметры -g/--globals-only и -r/--roles-only исключают друг друга" + +#: pg_dumpall.c:376 +#, c-format +msgid "" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "" +"параметры -g/--globals-only и -t/--tablespaces-only исключают друг друга" + +#: pg_dumpall.c:390 +#, c-format +msgid "" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "параметры -r/--roles-only и -t/--tablespaces-only исключают друг друга" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "не удалось подключиться к базе данных: \"%s\"" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"не удалось подключиться к базе данных \"postgres\" или \"template1\"\n" +"Укажите другую базу данных." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s экспортирует всё содержимое кластера баз данных PostgreSQL в SQL-скрипт.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [ПАРАМЕТР]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=ИМЯ_ФАЙЛА имя выходного файла\n" + +#: pg_dumpall.c:633 +#, c-format +msgid "" +" -c, --clean clean (drop) databases before recreating\n" +msgstr "" +" -c, --clean очистить (удалить) базы данных перед\n" +" восстановлением\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr "" +" -g, --globals-only выгрузить только глобальные объекты, без баз\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner не восстанавливать владение объектами\n" + +#: pg_dumpall.c:637 +#, c-format +msgid "" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr "" +" -r, --roles-only выгрузить только роли, без баз данных\n" +" и табличных пространств\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr "" +" -S, --superuser=ИМЯ имя пользователя для выполнения выгрузки\n" + +#: pg_dumpall.c:640 +#, c-format +msgid "" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr "" +" -t, --tablespaces-only выгружать только табличные пространства,\n" +" без баз данных и ролей\n" + +#: pg_dumpall.c:646 +#, c-format +msgid "" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr "" +" --exclude-database=ШАБЛОН исключить базы с именами, подпадающими под " +"шаблон\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords не выгружать пароли ролей\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=СТРОКА подключиться с данной строкой подключения\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=ИМЯ_БД выбор другой базы данных по умолчанию\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the " +"standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Если не указан параметр -f/--file, SQL-скрипт записывается в стандартный " +"вывод.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "имя роли, начинающееся с \"pg_\", пропущено (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "" +"не удалось разобрать список управления доступом (%s) для табл. пространства " +"\"%s\"" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "база данных \"%s\" исключается" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "выгрузка базы данных \"%s\"" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "ошибка при обработке базы \"%s\", pg_dump завершается" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "не удалось повторно открыть выходной файл \"%s\": %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "выполняется \"%s\"" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "не удалось узнать версию сервера" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "не удалось разобрать строку версии сервера \"%s\"" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "выполняется %s" + +# TO REVEIW +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "необходимо указать -d/--dbname или -f/--file" + +# TO REVEIW +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "параметры -d/--dbname и -f/--file исключают друг друга" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "параметры -C/--create и -1/--single-transaction исключают друг друга" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "максимальное число параллельных заданий равно %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "параметр --single-transaction допускается только с одним заданием" + +#: pg_restore.c:408 +#, c-format +msgid "" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "нераспознанный формат архива \"%s\"; укажите \"c\", \"d\" или \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "при восстановлении проигнорировано ошибок: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s восстанавливает базу данных PostgreSQL из архива, созданного командой " +"pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [ПАРАМЕТР]... [ФАЙЛ]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=БД подключиться к указанной базе данных\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr "" +" -f, --file=ИМЯ_ФАЙЛА имя выходного файла (или - для вывода в stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr "" +" -F, --format=c|d|t формат файла (должен определяться автоматически)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list вывести краткое оглавление архива\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose выводить подробные сообщения\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Параметры, управляющие восстановлением:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only восстановить только данные, без схемы\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create создать целевую базу данных\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr "" +" -e, --exit-on-error выйти при ошибке (по умолчанию - продолжать)\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=ИМЯ восстановить указанный индекс\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr "" +" -j, --jobs=ЧИСЛО распараллелить восстановление на указанное " +"число заданий\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=ИМЯ_ФАЙЛА использовать оглавление из этого файла для\n" +" чтения/упорядочивания данных\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr "" +" -n, --schema=ИМЯ восстановить объекты только в этой схеме\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr "" +" -N, --exclude-schema=ИМЯ не восстанавливать объекты в этой схеме\n" + +# skip-rule: no-space-before-parentheses +# well-spelled: арг +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=ИМЯ(арг-ты) восстановить заданную функцию\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only восстановить только схему, без данных\n" + +#: pg_restore.c:488 +#, c-format +msgid "" +" -S, --superuser=NAME superuser user name to use for disabling " +"triggers\n" +msgstr "" +" -S, --superuser=ИМЯ имя суперпользователя для отключения " +"триггеров\n" + +#: pg_restore.c:489 +#, c-format +msgid "" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr "" +" -t, --table=ИМЯ восстановить заданное отношение (таблицу, " +"представление и т. п.)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=ИМЯ восстановить заданный триггер\n" + +#: pg_restore.c:491 +#, c-format +msgid "" +" -x, --no-privileges skip restoration of access privileges (grant/" +"revoke)\n" +msgstr "" +" -x, --no-privileges не восстанавливать права доступа\n" +" (назначение/отзыв)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr "" +" -1, --single-transaction выполнить восстановление в одной транзакции\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security включить защиту на уровне строк\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments не восстанавливать комментарии\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not " +"be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables не восстанавливать данные таблиц, которые\n" +" не удалось создать\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications не восстанавливать публикации\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels не восстанавливать метки безопасности\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions не восстанавливать подписки\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr "" +" --no-tablespaces не восстанавливать назначения табл. " +"пространств\n" + +#: pg_restore.c:503 +#, c-format +msgid "" +" --section=SECTION restore named section (pre-data, data, or " +"post-data)\n" +msgstr "" +" --section=РАЗДЕЛ восстановить заданный раздел\n" +" (pre-data, data или post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ИМЯ_РОЛИ выполнить SET ROLE перед восстановлением\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and " +"specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Параметры -I, -n, -N, -P, -t, -T и --section можно комбинировать и " +"указывать\n" +"несколько раз для выбора нескольких объектов.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Если имя входного файла не указано, используется стандартное устройство " +"ввода.\n" +"\n" + +#~ msgid "reading row security enabled for table \"%s.%s\"" +#~ msgstr "чтение информации о защите строк для таблицы \"%s.%s\"" + +#~ msgid "reading policies for table \"%s.%s\"" +#~ msgstr "чтение политик таблицы \"%s.%s\"" + +#~ msgid "pclose failed: %m" +#~ msgstr "ошибка pclose: %m" + +#~ msgid "WSAStartup failed: %d" +#~ msgstr "ошибка WSAStartup: %d" + +#~ msgid "could not write to large object (result: %lu, expected: %lu)" +#~ msgstr "не удалось записать большой объект (результат: %lu, ожидалось: %lu)" + +#~ msgid "connection to database \"%s\" failed: %s" +#~ msgstr "не удалось подключиться к базе \"%s\": %s" + +#~ msgid "" +#~ "aggregate function %s could not be dumped correctly for this database " +#~ "version; ignored" +#~ msgstr "" +#~ "агрегатная функция %s не может быть правильно выгружена для этой версии " +#~ "базы данных; функция проигнорирована" + +#~ msgid "could not connect to database \"%s\": %s" +#~ msgstr "не удалось подключиться к базе \"%s\": %s" + +#~ msgid "reading publication membership for table \"%s.%s\"" +#~ msgstr "чтение информации об участии в репликации таблицы \"%s.%s\"" + +#~ msgid "connecting to database \"%s\" as user \"%s\"" +#~ msgstr "подключение к базе \"%s\" с именем пользователя \"%s\"" + +#~ msgid "could not reconnect to database" +#~ msgstr "не удалось переподключиться к базе" + +#~ msgid "could not reconnect to database: %s" +#~ msgstr "не удалось переподключиться к базе: %s" + +#~ msgid "connection needs password" +#~ msgstr "для подключения необходим пароль" + +#~ msgid "" +#~ "could not find block ID %d in archive -- possibly due to out-of-order " +#~ "restore request, which cannot be handled due to lack of data offsets in " +#~ "archive" +#~ msgstr "" +#~ "не удалось найти в архиве блок с ID %d -- возможно, по причине не " +#~ "последовательного запроса восстановления, который нельзя обработать из-за " +#~ "отсутствия смещений данных в архиве" + +#~ msgid "ftell mismatch with expected position -- ftell used" +#~ msgstr "позиция ftell не соответствует ожидаемой -- используется ftell" + +#~ msgid "internal error -- neither th nor fh specified in tarReadRaw()" +#~ msgstr "внутренняя ошибка -- в tarReadRaw() не указан ни th, ни fh" + +#~ msgid "Report bugs to .\n" +#~ msgstr "Об ошибках сообщайте по адресу .\n" + +#~ msgid "child process was terminated by signal %s" +#~ msgstr "дочерний процесс завершён по сигналу %s" + +#~ msgid "compress_io" +#~ msgstr "compress_io" + +#~ msgid "parallel archiver" +#~ msgstr "параллельный архиватор" + +#~ msgid "archiver" +#~ msgstr "архиватор" + +#~ msgid "-C and -1 are incompatible options\n" +#~ msgstr "Параметры -C и -1 несовместимы\n" + +#~ msgid "attempting to ascertain archive format\n" +#~ msgstr "попытка выяснить формат архива\n" + +#~ msgid "allocating AH for %s, format %d\n" +#~ msgstr "выделение структуры AH для %s, формат %d\n" + +#~ msgid "read TOC entry %d (ID %d) for %s %s\n" +#~ msgstr "прочитана запись оглавления %d (ID %d): %s %s\n" + +#~ msgid "could not set default_with_oids: %s" +#~ msgstr "не удалось установить параметр default_with_oids: %s" + +#~ msgid "entering restore_toc_entries_prefork\n" +#~ msgstr "вход в restore_toc_entries_prefork\n" + +#~ msgid "entering restore_toc_entries_parallel\n" +#~ msgstr "вход в restore_toc_entries_parallel\n" + +#~ msgid "entering restore_toc_entries_postfork\n" +#~ msgstr "вход в restore_toc_entries_postfork\n" + +#~ msgid "no item ready\n" +#~ msgstr "элемент не готов\n" + +#~ msgid "transferring dependency %d -> %d to %d\n" +#~ msgstr "переключение зависимости %d -> %d на %d\n" + +#~ msgid "reducing dependencies for %d\n" +#~ msgstr "уменьшение зависимостей для %d\n" + +#~ msgid "custom archiver" +#~ msgstr "внешний архиватор" + +#~ msgid "archiver (db)" +#~ msgstr "архиватор (БД)" + +#~ msgid "failed to reconnect to database\n" +#~ msgstr "ошибка переподключения к базе данных\n" + +#~ msgid "failed to connect to database\n" +#~ msgstr "ошибка подключения к базе данных\n" + +#~ msgid "directory archiver" +#~ msgstr "каталоговый архиватор" + +#~ msgid "tar archiver" +#~ msgstr "архиватор tar" + +#~ msgid "moving from position %s to next member at file position %s\n" +#~ msgstr "переход от позиции %s к следующему компоненту в позиции %s\n" + +#~ msgid "now at file position %s\n" +#~ msgstr "текущая позиция в файле %s\n" + +#~ msgid "skipping tar member %s\n" +#~ msgstr "пропускается компонент tar %s\n" + +# skip-rule: capital-letter-first +#~ msgid "TOC Entry %s at %s (length %s, checksum %d)\n" +#~ msgstr "Запись оглавления %s в %s (длина: %s, контр. сумма: %d)\n" + +#~ msgid "" +#~ "options --inserts/--column-inserts and -o/--oids cannot be used together\n" +#~ msgstr "" +#~ "параметры --inserts/--column-inserts и -o/--oids исключают друг друга\n" + +#~ msgid "(The INSERT command cannot set OIDs.)\n" +#~ msgstr "(В INSERT нельзя определять OID.)\n" + +#~ msgid " -o, --oids include OIDs in dump\n" +#~ msgstr " -o, --oids выгружать данные с OID\n" + +#~ msgid "sorter" +#~ msgstr "sorter" + +#~ msgid "%s: option --if-exists requires option -c/--clean\n" +#~ msgstr "%s: параметр --if-exists требует указания -c/--clean\n" + +#~ msgid "%s: could not open the output file \"%s\": %s\n" +#~ msgstr "%s: не удалось открыть выходной файл \"%s\": %s\n" + +#~ msgid "%s: invalid client encoding \"%s\" specified\n" +#~ msgstr "%s: указана неверная клиентская кодировка \"%s\"\n" + +#~ msgid "%s: executing %s\n" +#~ msgstr "%s: выполняется %s\n" + +#~ msgid "%s: query failed: %s" +#~ msgstr "%s: ошибка при выполнении запроса: %s" + +#~ msgid "%s: query was: %s\n" +#~ msgstr "%s: запрос: %s\n" + +#~ msgid "" +#~ "%s: options -s/--schema-only and -a/--data-only cannot be used together\n" +#~ msgstr "" +#~ "%s: параметры -s/--schema-only и -a/--data-only исключают друг друга\n" + +#~ msgid "%s: options -c/--clean and -a/--data-only cannot be used together\n" +#~ msgstr "%s: параметры -c/--clean and -a/--data-only исключают друг друга\n" + +#~ msgid "%s: invalid number of parallel jobs\n" +#~ msgstr "%s: неверное число параллельных заданий\n" + +#~ msgid "%s: could not parse ACL list (%s) for database \"%s\"\n" +#~ msgstr "" +#~ "%s: не удалось разобрать список управления доступом (%s) для базы данных " +#~ "\"%s\"\n" + +#~ msgid "reading extended statistics for table \"%s.%s\"\n" +#~ msgstr "чтение расширенной статистики для таблицы \"%s.%s\"\n" + +#~ msgid "setting owner and privileges for %s \"%s.%s\"\n" +#~ msgstr "установка владельца и прав: %s \"%s.%s\"\n" + +#~ msgid "setting owner and privileges for %s \"%s\"\n" +#~ msgstr "установка владельца и прав: %s \"%s\"\n" + +#~ msgid "" +#~ "Synchronized snapshots are not supported on standby servers.\n" +#~ "Run with --no-synchronized-snapshots instead if you do not need\n" +#~ "synchronized snapshots.\n" +#~ msgstr "" +#~ "На резервных серверах синхронизированные снимки не поддерживаются.\n" +#~ "Если они вам не нужны, укажите при запуске ключ\n" +#~ "--no-synchronized-snapshots.\n" + +#~ msgid "reading partition information\n" +#~ msgstr "чтение информации о секциях\n" + +#~ msgid "finding partition relationships\n" +#~ msgstr "обнаружение взаимосвязей секций\n" + +#~ msgid "reading partition key information for interesting tables\n" +#~ msgstr "чтение информации о ключах разбиения для интересующих таблиц\n" + +#~ msgid "" +#~ " --no-subscription-connect dump subscriptions so they don't connect " +#~ "on restore\n" +#~ msgstr "" +#~ " --no-subscription-connect выгружать подписки так, чтобы они не " +#~ "подключались\n" +#~ " при восстановлении\n" + +#~ msgid "" +#~ "%s: options --no-role-passwords and --binary-upgrade cannot be used " +#~ "together\n" +#~ msgstr "" +#~ "%s: параметры --no-role-passwords и --binary-upgrade исключают друг " +#~ "друга\n" + +#~ msgid "error processing a parallel work item\n" +#~ msgstr "ошибка выполнения части параллельной работы\n" + +#~ msgid "could not find slot of finished worker\n" +#~ msgstr "не удалось найти слот законченного рабочего объекта\n" + +#~ msgid "error during backup\n" +#~ msgstr "ошибка в процессе резервного копирования\n" + +#~ msgid "" +#~ "server version must be at least 7.3 to use schema selection switches\n" +#~ msgstr "" +#~ "для использования параметров выбора схемы нужен сервер версии 7.3 или " +#~ "новее\n" + +#~ msgid "query to get data of sequence \"%s\" returned name \"%s\"\n" +#~ msgstr "" +#~ "запрос на получение данных последовательности \"%s\" вернул имя \"%s\"\n" + +#~ msgid "could not get relation name for OID %u: %s\n" +#~ msgstr "не удалось получить имя отношения с OID %u: %s\n" + +#~ msgid "terminated by user\n" +#~ msgstr "прервано пользователем\n" + +#~ msgid "error in ListenToWorkers(): %s\n" +#~ msgstr "ошибка в ListenToWorkers(): %s\n" + +#~ msgid "worker is terminating\n" +#~ msgstr "рабочий процесс прерывается\n" + +#~ msgid "could not open output file \"%s\" for writing\n" +#~ msgstr "не удалось открыть выходной файл \"%s\" для записи\n" + +#~ msgid " -t, --table=NAME restore named table\n" +#~ msgstr " -t, --table=ИМЯ восстановить заданную таблицу\n" + +#~ msgid "archive member too large for tar format\n" +#~ msgstr "компонент архива слишком велик для формата tar\n" + +#~ msgid "could not write to custom output routine\n" +#~ msgstr "не удалось вывести данную в пользовательскую процедуру\n" + +#~ msgid "unexpected end of file\n" +#~ msgstr "неожиданный конец файла\n" + +#~ msgid "could not write byte: %s\n" +#~ msgstr "не удалось записать байт: %s\n" + +#~ msgid "could not write byte\n" +#~ msgstr "не удалось записать байт\n" + +#~ msgid "could not write null block at end of tar archive\n" +#~ msgstr "не удалось записать нулевой блок в конец tar-архива\n" + +#~ msgid "could not output padding at end of tar member\n" +#~ msgstr "не удалось записать выравнивание для компонента tar\n" + +#~ msgid "mismatch in actual vs. predicted file position (%s vs. %s)\n" +#~ msgstr "реальная позиция в файле отличается от предсказанной (%s и %s)\n" + +#~ msgid "could not determine seek position in file: %s\n" +#~ msgstr "не удалось определить позицию в файле: %s\n" + +#~ msgid "Error processing a parallel work item.\n" +#~ msgstr "Ошибка выполнения части параллельной работы.\n" + +#~ msgid "pgpipe could not getsockname: %ui" +#~ msgstr "функция pgpipe не смогла получить имя сокета: %ui" + +#~ msgid "pgpipe could not create socket 2: %ui" +#~ msgstr "функция pgpipe не смогла создать сокет 2: %ui" + +#~ msgid "worker process crashed: status %d\n" +#~ msgstr "крах рабочего процесса: состояние %d\n" + +#~ msgid "parallel_restore should not return\n" +#~ msgstr "неожиданный выход из parallel_restore\n" + +#~ msgid "could not parse version string \"%s\"\n" +#~ msgstr "не удалось разобрать строку версии \"%s\"\n" + +#~ msgid "%s: could not parse version \"%s\"\n" +#~ msgstr "%s: не удалось разобрать строку версии \"%s\"\n" + +#~ msgid "-C and -c are incompatible options\n" +#~ msgstr "Параметры -C и -c несовместимы\n" + +#~ msgid "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n" +#~ msgstr "" +#~ "неверный оператор COPY -- слово \"copy\" не найдено в строке \"%s\"\n" + +#~ msgid "" +#~ "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" " +#~ "starting at position %lu\n" +#~ msgstr "" +#~ "неверный оператор COPY -- указание \"from stdin\" не найдено в строке \"%s" +#~ "\", начиная с позиции %lu\n" + +#~ msgid "cannot create directory %s, it exists already\n" +#~ msgstr "создать каталог %s не удалось, он уже существует\n" + +#~ msgid "cannot create directory %s, a file with this name exists already\n" +#~ msgstr "создать каталог %s не удалось, так как есть файл с таким именем\n" + +#~ msgid "restoring large object OID %u\n" +#~ msgstr "восстановление большого объекта с OID %u\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help показать эту справку и выйти\n" + +#~ msgid "" +#~ " --version output version information, then exit\n" +#~ msgstr " --version показать версию и выйти\n" + +#~ msgid "*** aborted because of error\n" +#~ msgstr "*** аварийное завершение из-за ошибки\n" + +#~ msgid "missing pg_database entry for database \"%s\"\n" +#~ msgstr "для базы данных \"%s\" отсутствует запись в pg_database\n" + +#~ msgid "" +#~ "query returned more than one (%d) pg_database entry for database \"%s\"\n" +#~ msgstr "" +#~ "в pg_database нашлось несколько записей (%d) для базы данных \"%s\"\n" + +#~ msgid "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n" +#~ msgstr "dumpDatabase(): не удалось найти pg_largeobject.relfrozenxid\n" + +#~ msgid "" +#~ "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n" +#~ msgstr "" +#~ "dumpDatabase(): не удалось найти pg_largeobject_metadata.relfrozenxid\n" + +#~ msgid "query returned %d foreign server entry for foreign table \"%s\"\n" +#~ msgid_plural "" +#~ "query returned %d foreign server entries for foreign table \"%s\"\n" +#~ msgstr[0] "" +#~ "запрос вернул %d запись о стороннем сервере для сторонней таблицы \"%s\"\n" +#~ msgstr[1] "" +#~ "запрос вернул %d записи о стороннем сервере для сторонней таблицы \"%s\"\n" +#~ msgstr[2] "" +#~ "запрос вернул %d записей о стороннем сервере для сторонней таблицы \"%s" +#~ "\"\n" + +#~ msgid "missing pg_database entry for this database\n" +#~ msgstr "для этой базы данных отсутствует запись в pg_database\n" + +#~ msgid "found more than one pg_database entry for this database\n" +#~ msgstr "для этой базы данных найдено несколько записей в pg_database\n" + +#~ msgid "could not find entry for pg_indexes in pg_class\n" +#~ msgstr "для pg_indexes не найдена запись в pg_class\n" + +#~ msgid "found more than one entry for pg_indexes in pg_class\n" +#~ msgstr "для pg_indexes найдено несколько записей в pg_class\n" + +#~ msgid "SQL command failed\n" +#~ msgstr "ошибка SQL-команды\n" + +#~ msgid "file archiver" +#~ msgstr "файловый архиватор" + +#~ msgid "" +#~ "WARNING:\n" +#~ " This format is for demonstration purposes; it is not intended for\n" +#~ " normal use. Files will be written in the current working directory.\n" +#~ msgstr "" +#~ "ПРЕДУПРЖДЕНИЕ:\n" +#~ " Этот формат предназначен только для целей демонстрации, но не для\n" +#~ " повседневного использования. Файлы сохраняются в текущий рабочий " +#~ "каталог.\n" + +#~ msgid "could not close data file after reading\n" +#~ msgstr "не удалось закрыть файл данных после чтения\n" + +#~ msgid "could not open large object TOC for input: %s\n" +#~ msgstr "" +#~ "не удалось открыть для чтения файл оглавления больших объектов: %s\n" + +#~ msgid "could not open large object TOC for output: %s\n" +#~ msgstr "" +#~ "не удалось открыть для записи файл оглавления больших объектов: %s\n" + +#~ msgid "could not close large object file\n" +#~ msgstr "не удалось закрыть файл большого объекта\n" + +#~ msgid "" +#~ " -c, --clean clean (drop) database objects before " +#~ "recreating\n" +#~ msgstr "" +#~ " -c, --clean очистить (удалить) объекты БД при " +#~ "восстановлении\n" + +#~ msgid " -O, --no-owner skip restoration of object ownership\n" +#~ msgstr " -O, --no-owner не восстанавливать владение объектами\n" + +#~ msgid "" +#~ " --disable-triggers disable triggers during data-only restore\n" +#~ msgstr "" +#~ " --disable-triggers отключить триггеры при восстановлении только " +#~ "данных\n" + +#~ msgid "" +#~ " --use-set-session-authorization\n" +#~ " use SET SESSION AUTHORIZATION commands instead " +#~ "of\n" +#~ " ALTER OWNER commands to set ownership\n" +#~ msgstr "" +#~ " --use-set-session-authorization\n" +#~ " устанавливать владельца, используя команды\n" +#~ " SET SESSION AUTHORIZATION вместо ALTER OWNER\n" + +#~ msgid "%s: out of memory\n" +#~ msgstr "%s: нехватка памяти\n" diff --git a/src/bin/pg_dump/po/sv.po b/src/bin/pg_dump/po/sv.po new file mode 100644 index 0000000..5743c0e --- /dev/null +++ b/src/bin/pg_dump/po/sv.po @@ -0,0 +1,2718 @@ +# Swedish message translation file for pg_dump +# Peter Eisentraut , 2001, 2009, 2010. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-04-21 22:34+0000\n" +"PO-Revision-Date: 2022-02-18 15:33+0100\n" +"Last-Translator: Dennis Björklund \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "fatalt: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "fel: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "varning: " + +#: ../../common/exec.c:136 ../../common/exec.c:253 ../../common/exec.c:299 +#, c-format +msgid "could not identify current directory: %m" +msgstr "kunde inte identifiera aktuell katalog: %m" + +#: ../../common/exec.c:155 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "ogiltig binär \"%s\"" + +#: ../../common/exec.c:205 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "kunde inte läsa binär \"%s\"" + +#: ../../common/exec.c:213 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "kunde inte hitta en \"%s\" att köra" + +#: ../../common/exec.c:269 ../../common/exec.c:308 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "kunde inte byta katalog till \"%s\": %m" + +#: ../../common/exec.c:286 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "kan inte läsa symbolisk länk \"%s\": %m" + +#: ../../common/exec.c:409 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() misslyckades: %m" + +#: ../../common/exec.c:522 ../../common/exec.c:567 ../../common/exec.c:659 +msgid "out of memory" +msgstr "slut på minne" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "kommandot är inte körbart" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "kommandot kan ej hittas" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "barnprocess avslutade med kod %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "barnprocess terminerades med avbrott 0x%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "barnprocess terminerades av signal %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "barnprocess avslutade med okänd statuskod %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "läser utökningar" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "identifierar utökningsmedlemmar" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "läser scheman" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "läser användardefinierade tabeller" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "läser användardefinierade funktioner" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "läser användardefinierade typer" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "läser procedurspråk" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "läser användardefinierade aggregatfunktioner" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "läser användardefinierade operatorer" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "läser användardefinierade accessmetoder" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "läser användardefinierade operatorklasser" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "läser användardefinierade operator-familjer" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "läser användardefinierade textsöktolkare" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "läser användardefinierade textsökmallar" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "läser användardefinierade textsökordlistor" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "läser användardefinierade textsökkonfigurationer" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "läser användardefinierade främmande data-omvandlare" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "läser användardefinierade främmande servrar" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "läser standardrättigheter" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "läser användardefinierade jämförelser" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "läser användardefinierade konverteringar" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "läser typomvandlingar" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "läser transformer" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "läser information om arv av tabeller" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "läser händelseutlösare" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "hittar utökningstabeller" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "hittar arvrelationer" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "läser kolumninfo flr intressanta tabeller" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "markerar ärvda kolumner i undertabeller" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "läser index" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "flaggar index i partitionerade tabeller" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "läser utökad statistik" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "läser integritetsvillkor" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "läser utlösare" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "läser omskrivningsregler" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "läser policys" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "läser publiceringar" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "läser publiceringsmedlemskap" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "läser prenumerationer" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "ogiltigt antal (%d) föräldrar för tabell \"%s\"" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "misslyckades med riktighetskontroll, hittade inte förälder-OID %u för tabell \"%s\" (OID %u)" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "kunde inte tolka numerisk array \"%s\": för många nummer" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "kunde inte tolka numerisk array \"%s\": ogiltigt tecken i nummer" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "ogiltig komprimeringskod: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "ej byggt med zlib-stöd" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "kunde inte initiera komprimeringsbibliotek: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "kunde inte stänga komprimeringsströmmen: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "kunde inte komprimera data: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "kunde inte packa upp data: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "kunde inte stänga komprimeringsbiblioteket: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "kunde inte läsa från infilen: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "kunde inte läsa från infilen: slut på filen" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s() misslyckades: felkod %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "kunde inte skapa kommunikationskanaler: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "kunde inte skapa arbetsprocess: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "okänt kommando mottaget från ledare: \"%s\"" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "ogiltigt meddelande mottaget från arbetare: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"kunde inte låsa relationen \"%s\"\n" +"Dette beror oftast på att någon tagit ett ACCESS EXCLUSIVE-lås på tabellen\n" +"efter att pg_dumps föräldraprocess tagit ett ACCESS SHARE-lås på tabellen." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "en arbetsprocess dog oväntat" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "kunde inte skriva till kommunikationskanal: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: kunde inte skapa uttag (socket): felkod %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: kunde inte göra \"bind\": felkod %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: kunde inte göra \"listen\": felkod %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s() misslyckades: felkod %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: kunde inte skapa ett andra uttag (socket): felkod %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: kunde itne ansluta till uttag (socket): felkod %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: kunde inte acceptera anslutning: felkod %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "kunde inte stänga utdatafilen: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "arkivobjekten är inte i korrekt sektionsordning" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "oväntad sektionskod %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "parallell återställning stöds inte med detta arkivformat" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "parallell återställning stöds inte med arkiv som skapats av en pre-8.0 pg_dump" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "kan inte återställa från komprimerat arkiv (inte konfigurerad med stöd för komprimering)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "kopplar upp mot databas för återställning" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "direkta databasuppkopplingar stöds inte i arkiv från före version 1.3" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "implicerad återställning av enbart data" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "tar bort %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "kunde inte hitta var IF EXISTS skulle stoppas in i sats \"%s\"" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "varning från orginaldumpfilen: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "skapar %s \"%s.%s\"" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "skapar %s \"%s\"" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "kopplar upp mot ny databas \"%s\"" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "processar %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "processar data för tabell \"%s.%s\"" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "kör %s %s" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "stänger av utlösare för %s" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "slår på utlösare för %s" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "internt fel -- WriteData kan inte anropas utanför kontexten av en DataDumper-rutin" + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "utmatning av stora objekt stöds inte i det valda formatet" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "återställde %d stor objekt" +msgstr[1] "återställde %d stora objekt" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "återställer stort objekt med OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "kunde inte skapa stort objekt %u: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "kunde inte öppna stort objekt %u: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "kunde inte öppna TOC-filen \"%s\": %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "rad ignorerad: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "kunde inte hitta en post för ID %d" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "kunde inte stänga TOC-filen: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "kunde inte öppna utdatafilen \"%s\": %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "kunde inte öppna utdatafilen: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "skrev %zu byte data av stort objekt (resultat = %d)" +msgstr[1] "skrev %zu bytes data av stort objekt (resultat = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "kunde inte skriva till stort objekt: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "vid INITIERING:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "vid HANTERING AV TOC:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "vid SLUTFÖRANDE:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "från TOC-post %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "felaktigt dumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "felaktig tabell-dumpId för TABLE DATA-objekt" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "oväntad data-offset-flagga %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "fil-offset i dumpfilen är för stort" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "katalognamn för långt: \"%s\"" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "katalogen \"%s\" verkar inte vara ett giltigt arkiv (\"toc.dat\" finns inte)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "kunde inte öppna indatafilen \"%s\": %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "kan inte öppna infil: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "kan inte läsa infilen: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "indatafilen är för kort (läste %lu, förväntade 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "indatafilen verkar vara en dump i textformat. Använd psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "indatafilen verkar inte vara ett korrekt arkiv (för kort?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "indatafilen verkar inte vara ett korrekt arkiv" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "kunde inte stänga indatafilen: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "känner inte igen filformat \"%d\"" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "klar med objekt %d %s %s" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "arbetsprocess misslyckades: felkod %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "post-ID %d utanför sitt intervall -- kanske en trasig TOC" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "återeställa tabeller med WITH OIDS stöds inte längre" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "okänd teckenkodning \"%s\"" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "ogiltigt ENCODING-val: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "ogiltigt STDSTRINGS-val: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "schema \"%s\" hittades inte" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "tabell \"%s\" hittades inte" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "index \"%s\" hittades inte" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "funktion \"%s\" hittades inte" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "utlösare \"%s\" hittades inte" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "kunde inte sätta sessionsanvändare till \"%s\": %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "kunde inte sätta search_path till \"%s\": %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "kunde inte sätta default_tablespace till %s: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "kunde inte sätta default_table_access_method: %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "vet inte hur man sätter ägare för objekttyp \"%s\"" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "kunde inte hitta den magiska strängen i filhuvudet" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "ej supportad version (%d.%d) i filhuvudet" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "riktighetskontroll på heltalsstorlek (%lu) misslyckades" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "arkivet skapades på en maskin med större heltal, en del operationer kan misslyckas" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "förväntat format (%d) skiljer sig från formatet som fanns i filen (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "arkivet är komprimerat, men denna installation stödjer inte komprimering -- ingen data kommer kunna läsas" + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "ogiltig skapandedatum i huvud" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "processar objekt %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "går in i parallella huvudloopen" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "hoppar över objekt %d %s %s" + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "startar objekt %d %s %s" + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "klar med parallella huvudloopen" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "processar saknat objekt %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "tabell \"%s\" kunde inte skapas, dess data kommer ej återställas" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "ogiltig OID för stort objekt" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "fel vid sökning: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "datablock %d har fel sökposition" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "känner inte igen datablocktyp (%d) vid genomsökning av arkiv" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "kunde inte hitta block ID %d i arkiv -- kanske på grund av en återställningbegäran i oordning vilket inte kan hanteras då inputfilen inte är sökbar" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "kunde inte hitta block ID %d i arkiv -- möjligen ett trasigt arkiv" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "hittade oväntat block-ID (%d) vid läsning av data -- förväntade %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "ej igenkänd datablockstyp %d vid återställande av arkiv" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "kunde inte läsa från infilen: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "kunde inte bestämma sökposition i arkivfil: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "kan inte stänga arkivfilen: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "kan inte återöppna indataarkiven" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "parallell återställning från standard in stöds inte" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "parallell återställning för en icke sökbar fil stöds inte" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "kunde inte söka till rätt position i arkivfilen: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "komprimerare aktiv" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "kunde inte hämta serverversionen från libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "server version: %s; %s version: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "avbryter då serverversionerna i matchar" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "är redan uppkopplad mot en databas" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Lösenord: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "kunde inte ansluta till databasen" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "återanslutning misslyckades: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "fråga misslyckades: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "frågan var: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "fråga gav %d rad istället för en: %s" +msgstr[1] "fråga gav %d rader istället för en: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s: %sKommandot var: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "kunde inte utföra fråga" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "fel returnerat av PQputCopyData: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "fel returnerat av PQputCopyEnd: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "COPY misslyckades för tabell \"%s\": %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "oväntade extraresultat under kopiering (COPY) av tabell \"%s\"" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "kunde inte starta databastransaktionen" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "kunde inte genomföra databastransaktionen" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "ingen utdatakatalog angiven" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "kunde inte stänga katalog \"%s\": %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "kunde inte skapa katalog \"%s\": %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "kunde inte skriva till utdatafil: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "kan inte stänga datafil: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "kan inte stänga datafil \"%s\": %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "kunde inte öppna stora objekts TOC-fil \"%s\" för läsning: %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "ogiltig rad i stora objekts TOC-fil \"%s\": \"%s\"" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "fel vid lösning av stora objekts TOC-fil \"%s\"" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "kunde inte stänga stora objekts TOC-fil \"%s\": %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "kan inte stänga blobbars datafil: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "kunde inte skriva till blobbars TOC-fil" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "kunde inte stänga blobbars TOC-fil: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "filnamnet är för långt: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "detta format kan inte läsas" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "kunde inte öppna TOC-filen \"%s\" för utmatning: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "kunde inte öppna TOC-filen för utmatning: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "komprimering är stödjs inte av arkivformatet tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "kunde inte öppna TOC-fil \"%s\" för läsning: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "kunde inte öppna TOC-fil för läsning: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "kunde inte hitta fil \"%s\" i arkiv" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "kunde inte generera temporärt filnamn: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "kunde inte öppna temporär fil" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "kunde inte stänga tar-medlem: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "oväntad COPY-satssyntax: \"%s\"" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "ogiltig OID för stort objekt (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "kunde inte stänga temporär fil: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "verklig fillängd (%s) matchar inte det förväntade (%s)" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "kunde inte hitta filhuvud för fil \"%s\" i tar-arkiv" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "dumpa data i oordning stöds inte av detta arkivformat: \"%s\" krävs, men kommer före \"%s\" i denna arkivfil." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "inkomplett tar-huvud hittat (%lu byte)" +msgstr[1] "inkomplett tar-huvud hittat (%lu bytes)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "trasigt tar-huvud hittat i %s (förväntade %d, beräknad %d) filposition %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "okänt sektionsnamn: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Försök med \"%s --help\" för mer information.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "slut på on_exit_nicely-slottar" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "komprimeringsnivå måste vara i intervallet 0..9" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits måste vara i intervallet -15..3" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert måste vara i intervallet %d..%d" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "för många kommandoradsargument (första är \"%s\")" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "flaggorna \"bara schema\" (-s) och \"bara data\" (-a) kan inte användas tillsammans" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "flaggorna -s/--schema-only och --include-foreign-data kan inte användas tillsammans" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "flaggan --include-foreign-data stöds inte med parallell backup" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "flaggorna \"nollställ\" (-c) och \"bara data\" (-a) kan inte användas tillsammans" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "flaggan --if-exists kräver flaggan -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "flagga --on-conflict-do-nothing kräver --inserts, --rows-per-insert eller --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "efterfrågad komprimering finns inte i denna installation -- arkivet kommer sparas okomprimerat" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "felaktigt antal parallella job" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "parallell backup stöds bara med katalogformat" + +#: pg_dump.c:787 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synkroniseringssnapshots stöds inte av denna serverversion.\n" +"Kör med --no-synchronized-snapshots istället om du inte kräver\n" +"synkroniserade snapshots." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Exporterade snapshots stöds inte i denna serverversion." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "sista inbyggda OID är %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "hittade inga matchande scheman" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "hittade inga matchande tabeller" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "hittade inga matchande utökningar" + +#: pg_dump.c:1020 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s dumpar en databas som en textfil eller i andra format.\n" +"\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Användning:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [FLAGGA]... [DBNAMN]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Allmänna flaggor:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=FILENAME fil eller katalognamn för utdata\n" + +#: pg_dump.c:1026 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p utdatans filformat (egen (c), katalog (d), tar (t),\n" +" ren text (p) (standard))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM använd så här många parellella job för att dumpa\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose visa mer information\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 komprimeringsnivå för komprimerade format\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT misslyckas efter att ha väntat i TIMEOUT på tabellås\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync vänta inte på att ändingar säkert skrivits till disk\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Flaggor som styr utmatning:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only dumpa bara data, inte schema\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs inkludera stora objekt i dumpen\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs exkludera stora objekt i dumpen\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean nollställ (drop) databasobjekt innan återskapande\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create inkludera kommandon för att skapa databasen i dumpen\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=MALL dumpa bara de angivna utökningarna\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=KODNING dumpa data i teckenkodning KODNING\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=MALL dumpa bara de angivna scheman\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=MALL dumpa INTE de angivna scheman\n" + +#: pg_dump.c:1046 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner hoppa över återställande av objektägare i\n" +" textformatdumpar\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only dumpa bara scheman, inte data\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME namn på superuser för textformatdumpar\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=MALL dumpa bara de angivna tabellerna\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=MALL dumpa INTE de angivna tabellerna\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges dumpa inte rättigheter (grant/revoke)\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade används bara av uppgraderingsverktyg\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts dumpa data som INSERT med kolumnnamn\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr " --disable-dollar-quoting slå av dollar-citering, använd standard SQL-citering\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers slå av utlösare vid återställning av enbart data\n" + +#: pg_dump.c:1057 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security slå på radsäkerhet (dumpa bara data användaren\n" +" har rätt till)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=MALL dumpa INTE data för de angivna tabellerna\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM övertrumfa standardinställningen för extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists använd IF EXISTS när objekt droppas\n" + +#: pg_dump.c:1062 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=MALL\n" +" inkludera data i främmande tabeller från\n" +" främmande servrar som matchar MALL\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts dumpa data som INSERT, istället för COPY\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root ladda partitioner via root-tabellen\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments dumpa inte kommentarer\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications dumpa inte publiceringar\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels dumpa inte tilldelning av säkerhetsetiketter\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions dumpa inte prenumereringar\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots använd inte synkroniserade snapshots i parallella job\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces dumpa inte användning av tabellutymmen\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression dumpa inte komprimeringsmetoder för TOAST\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data dumpa inte ologgad tabelldata\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing addera ON CONFLICT DO NOTHING till INSERT-kommandon\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers citera alla identifierar, även om de inte är nyckelord\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NRADER antal rader per INSERT; implicerar --inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=SEKTION dumpa namngiven sektion (pre-data, data eller post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable wait until the dump can run without anomalies\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT använda namngivet snapshot för att dumpa\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names kräv att mallar för tabeller och/eller scheman matchar\n" +" minst en sak var\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" använd kommandot SET SESSION AUTHORIZATION istället för\n" +" kommandot ALTER OWNER för att sätta ägare\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Flaggor för anslutning:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAMN databasens som skall dumpas\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT databasens värdport\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NAMN anslut med datta användarnamn mot databasen\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password fråga aldrig efter lösenord\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password fråga om lösenord (borde ske automatiskt)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLLNAMN gör SET ROLE innan dumpen\n" + +#: pg_dump.c:1096 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Om inget databasnamn anges, då kommer värdet i omgivningsvariabel\n" +"PGDATABASE att användas.\n" +"\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Rapportera fel till <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "hemsida för %s: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "ogiltig klientteckenkodning \"%s\" angiven" + +#: pg_dump.c:1264 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Synkroniserade snapshots på standby-servrar stöds inte av denna serverversion.\n" +"Kör med --no-synchronized-snapshots istället om du inte behöver\n" +"synkroniserade snapshots." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "ogiltigt utdataformat \"%s\" angivet" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "ej korrekt kvalificerat namn (för många namn med punkt): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "hittade inga matchande scheman för mallen \"%s\"" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "hittade inga matchande utökningar för mallen \"%s\"" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "hittade inga matchande främmande servrar för mallen \"%s\"" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "ej korrekt relationsnamn (för många namn med punkt): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "hittade inga matchande tabeller för mallen \"%s\"" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "Du är för närvarande inte uppkopplad mot en databas." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "referenser till andra databaser är inte implementerat: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "dumpar innehållet i tabell \"%s.%s\"" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Dumpning av innehållet i tabellen \"%s\" misslyckades: PQendcopy() misslyckades." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Felmeddelandet från servern: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "Kommandot var: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Dumpning av innehållet i tabellen \"%s\" misslyckades: PQgetResult() misslyckades." + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "fel antal fält hämtades för tabell \"%s\"" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "sparar databasdefinition" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "sparar kodning = %s" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "sparar standard_conforming_strings = %s" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "kunde inte parsa resultat från current_schemas()" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "sparar search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "läser stora objekt" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "sparar stora objekt" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "fel vid läsning av stort objekt %u: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "läser säkerhetspolicy på radnivå" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "oväntad kommandotyp för policy: %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "ägare av publicering \"%s\" verkar vara ogiltig" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "prenumerationer har inte dumpats få aktuell användare inte är en superuser" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "ägare av prenumeration \"%s\" verkar vara ogiltig" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "kunde inte parsa arrayen för subpubliceringar" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "kunde inte hitta föräldrautökning för %s %s" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "ägare av schema \"%s\" verkar vara ogiltig" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "schema med OID %u existerar inte" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "ägare av datatyp \"%s\" verkar vara ogiltig" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "ägare av operator \"%s\" verkar vara ogiltig" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "ägare av operatorklass \"%s\" verkar vara ogiltig" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "ägare av operator-familj \"%s\" verkar vara ogiltig" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "ägare av aggregatfunktion \"%s\" verkar vara ogiltig" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "ägare av funktion \"%s\" verkar vara ogiltig" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "ägare av tabell \"%s\" verkar vara ogiltig" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "misslyckades med riktighetskontroll, föräldratabell med OID %u för sekvens med OID %u hittas inte" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "läser index för tabell \"%s.%s\"" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "läser främmande nyckel-villkor för tabell \"%s.%s\"" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "misslyckades med riktighetskontroll, föräldratabell med OID %u för pg_rewrite-rad med OID %u hittades inte" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "läser utlösare för tabell \"%s.%s\"" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "fråga producerade null som refererad tabell för främmande nyckel-utlösare \"%s\" i tabell \"%s\" (OID för tabell : %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "hittar kolumner och typer för tabell \"%s.%s\"" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "ogiltigt kolumnnumrering i tabell \"%s\"" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "hittar default-uttryck för tabell \"%s.%s\"" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "felaktigt adnum-värde %d för tabell \"%s\"" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "hittar check-villkor för tabell \"%s.%s\"" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "förväntade %d check-villkor för tabell \"%s\" men hittade %d" +msgstr[1] "förväntade %d check-villkor för tabell \"%s\" men hittade %d" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(systemkatalogerna kan vara trasiga.)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "typtype för datatyp \"%s\" verkar vara ogiltig" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "felaktigt värde i arrayen proargmodes" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "kunde inte tolka arrayen proallargtypes" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "kunde inte tolka arrayen proargmodes" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "kunde inte tolka arrayen proargnames" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "kunde inte tolka arrayen proconfig" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "okänt provolatile-värde för funktion \"%s\"" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "okänt proparallel-värde för funktion \"%s\"" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "kunde inte hitta funktionsdefinitionen för funktion med OID %u" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "felaktigt värde i fältet pg_cast.castfunc eller pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "felaktigt värde i fältet pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "felaktig transform-definition, minst en av trffromsql och trftosql måste vara ickenoll" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "felaktigt värde i fältet pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "felaktigt värde i fältet pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "postfix-operatorer stöds inte längre (operator \"%s\")" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "kunde inte hitta en operator med OID %s." + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "ogiltig typ \"%c\" för accessmetod \"%s\"" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "okänd jämförelseleverantör: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "okänt aggfinalmodify-värde för aggregat \"%s\"" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "okänt aggmfinalmodify-värde för aggregat \"%s\"" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "okänd objekttyp i standardrättigheter: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "kunde inte parsa standard-ACL-lista (%s)" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "kunde inte parsa initial GRANT ACL-lista (%s) eller initial REVOKE ACL-lista (%s) för objekt \"%s\" (%s)" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "kunde inte parsa GRANT ACL-lista (%s) eller REVOKE ACL-lista (%s) för objekt \"%s\" (%s)" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "fråga för att hämta definition av vy \"%s\" returnerade ingen data" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "fråga för att hämta definition av vy \"%s\" returnerade mer än en definition" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "definition av vy \"%s\" verkar vara tom (längd noll)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS stöds inte längre (tabell \"%s\")" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "ogiltigt kolumnnummer %d för tabell \"%s\"" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "kunde inte parsa kolumn i indexstatistik" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "kunde inte parsa värden i indexstatistik" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "antal kolumner och värden stämmer inte i indexstatistik" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "saknar index för integritetsvillkor \"%s\"" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "oväntad integritetsvillkorstyp: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "fråga för att hämta data för sekvens \"%s\" returnerade %d rad (förväntade 1)" +msgstr[1] "fråga för att hämta data för sekvens \"%s\" returnerade %d rader (förväntade 1)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "okänd sekvenstyp: %s" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "oväntat tgtype-värde: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "felaktig argumentsträng (%s) för utlösare \"%s\" i tabell \"%s\"" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "fråga för att hämta regel \"%s\" för tabell \"%s\" misslyckades: fel antal rader returnerades" + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "kunde inte hitta refererad utökning %u" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "kunde inte parsa konfigurations-array för utökning" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "kunde inte parsa villkors-array för utökning" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "antal konfigurationer och villkor stämmer inte för utökning" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "läser beroendedata" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "inget refererande objekt %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "inget refererat objekt %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "kunde inte parsa arrayen reloptions" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "ogiltigt dumpId %d" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "ogiltigt beroende %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "kunde inte fastställa beroendeloop" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "det finns cirkulära främmande nyckelberoenden för denna tabell:" +msgstr[1] "det finns cirkulära främmande nyckelberoenden för dessa tabeller:" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Du kan eventiellt inte återställa dumpen utan att använda --disable-triggers eller temporärt droppa vilkoren." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Överväg att göra en full dump istället för --data-only för att undvika detta problem." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "kunde inte räta ut beroendeloopen för dessa saker:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"Programmet \"%s\" behövs av %s men hittades inte i samma\n" +"katalog som \"%s\".\n" +"Kontrollera din installation." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"Programmet \"%s\" hittades av \"%s\"\n" +"men är inte av samma version som %s.\n" +"Kontrollera din installation." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "flaggan --exclude-database kan inte användas tillsammans med -g/--globals-only, -r/--roles-only eller -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "flaggorna \"bara gobala\" (-g) och \"bara roller\" (-r) kan inte användas tillsammans" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "flaggorna \"bara globala\" (-g) och \"bara tabellutrymmen\" (-t) kan inte användas tillsammans" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "flaggorna \"bara roller\" (-r) och \"bara tabellutrymmen\" (-t) kan inte användas tillsammans" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "kunde inte ansluta till databasen \"%s\"" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"kunde inte ansluta till databasen \"postgres\" eller \"template1\"\n" +"Ange en annan databas." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s extraherar ett PostgreSQL databaskluster till en SQL-scriptfil.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [FLAGGA]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=FILENAME utdatafilnamn\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean nollställ (drop) databaser innan återskapning\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only dumpa bara globala objekt, inte databaser\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner återställ inte objektägare\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only dumpa endast roller, inte databaser eller tabellutrymmen\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAMN namn på superuser för användning i dumpen\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only dumpa endasdt tabellutrymmen, inte databaser eller roller\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=MALL uteslut databaser vars namn matchar MALL\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords dumpa inte lösenord för roller\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=ANSLSTR anslut med anslutningssträng\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAMN alternativ standarddatabas\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Om -f/--file inte används så kommer SQL-skriptet skriva till standard ut.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "rollnamn som startar med \"pg_\" hoppas över (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "kunde inte tolka ACL-listan (%s) för tabellutrymme \"%s\"" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "utesluter databas \"%s\"" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "dumpar databas \"%s\"" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump misslyckades med databas \"%s\", avslutar" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "kunde inte öppna om utdatafilen \"%s\": %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "kör \"%s\"" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "kunde inte hämta serverversionen" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "kunde inte tolka versionsträngen \"%s\"" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "kör: %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "en av flaggorna -d/--dbname och -f/--file måste anges" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "flaggorna -d/--dbname och -f/--file kan inte användas ihop" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "flaggorna -C/--create och -1/--single-transaction kan inte användas tillsammans" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "maximalt antal parallella job är %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "kan inte ange både --single-transaction och multipla job" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "okänt arkivformat \"%s\"; vänligen ange \"c\", \"d\" eller \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "fel ignorerade vid återställande: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s återställer en PostgreSQL-databas från ett arkiv skapat av pg_dump.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [FLAGGA]... [FIL]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAMN koppla upp med databasnamn\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FILNAMN utdatafilnamn (- för stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t backupens filformat (bör ske automatiskt)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list skriv ut summerad TOC för arkivet\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose visa mer information\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Flaggor som styr återställning:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only återställ bara data, inte scheman\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create skapa måldatabasen\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error avsluta vid fel, standard är att fortsätta\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAMN återställ namngivet index\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM använda så här många parallella job för återställning\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FILNAMN använd innehållsförteckning från denna fil för\n" +" att välja/sortera utdata\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAMN återställ enbart objekt i detta schema\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAMN återställ inte objekt i detta schema\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAMN(arg) återställ namngiven funktion\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only återställ bara scheman, inte data\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAMN namn på superuser för att slå av utlösare\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NAMN återställ namngiven relation (tabell, vy, osv.)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAMN återställ namngiven utlösare\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges återställ inte åtkomsträttigheter (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction återställ i en enda transaktion\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security aktivera radsäkerhet\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments återställ inte kommentarer\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables återställ inte data för tabeller som\n" +" inte kunde skapas\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications återställ inte publiceringar\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels återställ inte säkerhetsetiketter\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions återställ inte prenumerationer\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces återställ inte användning av tabellutymmen\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=SEKTION återställ namngiven sektion (pre-data, data eller post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME gör SET ROLE innan återställning\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"Flaggorna -I, -n, -N, -P, -t, -T och --section kan kombineras och anges\n" +"många gånger för att välja flera objekt.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Om inget indatafilnamn är angivet, så kommer standard in att användas.\n" +"\n" diff --git a/src/bin/pg_dump/po/tr.po b/src/bin/pg_dump/po/tr.po new file mode 100644 index 0000000..7ec7f5d --- /dev/null +++ b/src/bin/pg_dump/po/tr.po @@ -0,0 +1,3070 @@ +# translation of pg_dump-tr.po to Turkish +# Devrim GUNDUZ , 2004, 2006, 2007. +# Nicolai TUFAR 2004, 2005, 2006, 2007. +# Abdullah Gülner , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump-tr\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2019-04-26 13:47+0000\n" +"PO-Revision-Date: 2019-05-31 15:16+0300\n" +"Last-Translator: Abdullah Gülner\n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.7.1\n" +"X-Poedit-Basepath: /home/ntufar/pg/pgsql/src/bin/pg_dump\n" +"X-Poedit-SearchPath-0: C:/pgsql/src/bin/pg_dump\n" +"X-Poedit-SearchPath-1: /home/ntufar/pg/pgsql/src/backend\n" +"X-Poedit-SearchPath-2: c:/pgsql/src/backend\n" + +#: ../../../src/fe_utils/logging.c:182 +#, c-format +msgid "fatal: " +msgstr "ölümcül (fatal): " + +#: ../../../src/fe_utils/logging.c:189 +#, c-format +msgid "error: " +msgstr "hata: " + +#: ../../../src/fe_utils/logging.c:196 +#, c-format +msgid "warning: " +msgstr "uyarı: " + +#: ../../common/exec.c:138 ../../common/exec.c:255 ../../common/exec.c:301 +#, c-format +msgid "could not identify current directory: %m" +msgstr "geçerli dizin tespit edilemedi: %m" + +#: ../../common/exec.c:157 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "geçersiz ikili (binary) \"%s\"" + +#: ../../common/exec.c:207 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "\"%s\" ikili (binary) dosyası okunamadı" + +#: ../../common/exec.c:215 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "\"%s\" çalıştırmak için bulunamadı" + +#: ../../common/exec.c:271 ../../common/exec.c:310 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "çalışma dizini \"%s\" olarak değiştirilemedi: %m" + +#: ../../common/exec.c:288 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "symbolic link \"%s\" okuma hatası: %m" + +#: ../../common/exec.c:541 +#, c-format +msgid "pclose failed: %m" +msgstr "pclose başarısız oldu: %m" + +#: ../../common/exec.c:670 ../../common/exec.c:715 ../../common/exec.c:807 +msgid "out of memory" +msgstr "yetersiz bellek" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 +#, c-format +msgid "out of memory\n" +msgstr "yetersiz bellek\n" + +#: ../../common/fe_memutils.c:92 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "null pointer çoğaltılamıyor (duplicate) (iç hata)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "komut çalıştırılabilir değil" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "komut bulunamadı" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "alt süreç %d çıkış koduyla sonuçlandırılmıştır" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "alt süreç 0x%X exception tarafından sonlandırılmıştır" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "alt süreç %d sinyali tarafından sonlandırılmıştır :%s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "alt süreç %d bilinmeyen durumu ile sonlandırılmıştır" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "uzantılar okunuyor" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "uzantı üyeleri belirleniyor" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "şemalar okunuyor" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "kullanıcı tanımlı tablolar okunuyor" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "kullanıcı tanımlı fonksiyonlar okunuyor" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "kullanıcı tanımlı tipler okunuyor" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "yordamsal diller okunuyor" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "kullanıcı-tanımlı aggregate fonksiyonlar okunuyor" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "kullanıcı tanımlı operatörler okunuyor" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "kullanıcı tanımlı erişim yöntemleri okunuyor" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "kullanıcı-tanımlı operatör sınıfları okunuyor" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "kullanıcı tanımlı operatör aileleri okunuyor" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "kullanıcı tanımlı metin arama ayrıştırıcıları okunuyor" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "kullanıcı tanımlı metin arama şablonları okunuyor" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "kullanıcı-tanımlı metin arama sözlükleri okunuyor" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "kullanıcı-tanımlı metin arama yapılandırmaları okunuyor" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "kullanıcı tanımlı foreign-data wrapperlar okunuyor" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "kullanıcı tanımlı foreign sunucular okunuyor" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "öntanımlı yetkiler okunuyor" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "kullanıcı tanımlı collation'lar okunuyor" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "kullanıcı tanımlı dönüşümler (conversion) okunuyor" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "type cast'lar okunuyor" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "dönüşümler (transform) okunuyor" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "tablo kalıtım (inheritance) bilgisi okunuyor" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "olay tetikleyicileri okunuyor" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "uzantı tabloları bulunuyor" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "kalıtım (inheritance) ilişkileri bulunuyor" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "ilgili tabloların sütun bilgisi okunuyor" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "alt tablolarda inherited sütunlar işaretleniyor" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "indeksler okunuyor" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "bölümlenmiş tablolardaki indeksler işaretleniyor" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "genişletilmiş istatistikler okunuyor" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "bütünlük kısıtlamaları okunuyor" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "tetikleyiciler okunuyor" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "rewrite kuralları okunuyor" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "ilkeler (policy) okunuyor" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "yayınlar (publication) okunuyor" + +#: common.c:255 +#, c-format +msgid "reading publication membership" +msgstr "yayın üyeliği okunuyor" + +#: common.c:258 +#, c-format +msgid "reading subscriptions" +msgstr "abonelikler okunuyor" + +#: common.c:1024 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "tutarlılık kontrolü başarısız, \"%2$s\" tablosunun (OID %3$u) üst OIDsi %1$u bulunamadı" + +#: common.c:1066 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "\"%s\" numerik dizisi ayrıştırılamadı: çok fazla sayı" + +#: common.c:1081 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "\"%s\" numerik dizisi ayrıştırılamadı: sayıda geçersiz karakter" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "geçersiz sıkıştırma kodu: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:508 +#: compress_io.c:551 +#, c-format +msgid "not built with zlib support" +msgstr "zlib desteğiyle oluşturulmamış" + +#: compress_io.c:237 compress_io.c:336 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "sıkıştırma kütüphanesi ilklendirilemedi: %s" + +#: compress_io.c:257 +#, c-format +msgid "could not close compression stream: %s" +msgstr "sıkıştırma akımı kapatılamadı: %s" + +#: compress_io.c:274 +#, c-format +msgid "could not compress data: %s" +msgstr "veri sıkıştırılamadı: %s" + +#: compress_io.c:352 compress_io.c:367 +#, c-format +msgid "could not uncompress data: %s" +msgstr "sıkıştırılmış veri açılamadı: %s" + +#: compress_io.c:374 +#, c-format +msgid "could not close compression library: %s" +msgstr "sıkıştırma kütüphanesi kapatılamadı: %s" + +#: compress_io.c:588 compress_io.c:625 pg_backup_tar.c:555 pg_backup_tar.c:558 +#, c-format +msgid "could not read from input file: %s" +msgstr "girdi dosyası okuma hatası: %s" + +#: compress_io.c:627 pg_backup_custom.c:578 pg_backup_directory.c:539 +#: pg_backup_tar.c:795 pg_backup_tar.c:818 +#, c-format +msgid "could not read from input file: end of file" +msgstr "girdi dosyası okuma hatası: dosya sonu" + +#: parallel.c:263 +#, c-format +msgid "WSAStartup failed: %d" +msgstr "WSAStartup başarısız: %d" + +#: parallel.c:968 +#, c-format +msgid "could not create communication channels: %m" +msgstr "iletişim kanalları oluşturulamadı: %m" + +#: parallel.c:1031 +#, c-format +msgid "could not create worker process: %m" +msgstr "işçi süreci yaratılamadı: %m" + +#: parallel.c:1160 +#, c-format +msgid "unrecognized command received from master: \"%s\"" +msgstr "ana sunucudan (master) bilinmeyen komut alındı: \"%s\"" + +#: parallel.c:1203 parallel.c:1441 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "alt süreçten (worker) geçersiz mesaj alındı: \"%s\"" + +#: parallel.c:1335 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"\"%s\" nesnesi üzerinde kilit alınamadı\n" +"Bu genellikle pg_dump ana süreci tablo üzerinde başta ACCESS SHARE kilidi aldıktan sonra başka birinin tablo üzerinde ACCESS EXCLUSIVE kilidi talep ettiği anlamına gelir." + +#: parallel.c:1424 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "alt süreç beklenmeyen biçimde sonlandı" + +#: parallel.c:1546 parallel.c:1662 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "iletişim kanalına yazma başarısız: %m" + +#: parallel.c:1623 +#, c-format +msgid "select() failed: %m" +msgstr "select() başarısız oldu: %m" + +#: parallel.c:1746 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: soket oluşturulamadı: hata kodu %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: bağlanamadı (bind): hata kodu %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: dinleyemedi: hata kodu %d" + +#: parallel.c:1771 +#, c-format +msgid "pgpipe: getsockname() failed: error code %d" +msgstr "pgpipe: getsockname() başarısız oldu: hata kodu %d" + +#: parallel.c:1782 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: ikinci soket oluşturulamadı: hata kodu %d" + +#: parallel.c:1791 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: soket bağlanamadı: hata kodu %d" + +#: parallel.c:1800 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: bağlantı kabul edemedi: hata kodu %d" + +#: pg_backup_archiver.c:273 pg_backup_archiver.c:1596 +#, c-format +msgid "could not close output file: %m" +msgstr "çıktı dosyası kapatılamadı: %m" + +#: pg_backup_archiver.c:317 pg_backup_archiver.c:321 +#, c-format +msgid "archive items not in correct section order" +msgstr "arşiv kalemleri doğru bölüm sırasında değil" + +#: pg_backup_archiver.c:327 +#, c-format +msgid "unexpected section code %d" +msgstr "beklenmeyen bölüm kodu %d" + +#: pg_backup_archiver.c:364 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "paralel geri yükleme bu arşiv dosya biçimiyle desteklenmiyor" + +#: pg_backup_archiver.c:368 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "paralel geri yükleme özelliği 8.0 öncesi pg_dump ile yapılan arşivlerle desteklenmemektedir" + +#: pg_backup_archiver.c:386 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "sıkıştırılmış arşivden yükleme başarısız (bu kurulumda sıkıştırma desteklenmiyor)" + +#: pg_backup_archiver.c:403 +#, c-format +msgid "connecting to database for restore" +msgstr "geri yükleme için veritabanına bağlanılıyor" + +#: pg_backup_archiver.c:405 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "1.3 sürüm öncesi arşivlerinde doğrudan veritabanı bağlantıları desteklenmemektedir" + +#: pg_backup_archiver.c:450 +#, c-format +msgid "implied data-only restore" +msgstr "örtük salt veri geri yükleme" + +#: pg_backup_archiver.c:516 +#, c-format +msgid "dropping %s %s" +msgstr "%s %s kaldırılıyor" + +#: pg_backup_archiver.c:611 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "\"%s\" ifadesinde nereye IF EXISTS ekleneceği bulunamadı" + +#: pg_backup_archiver.c:767 pg_backup_archiver.c:769 +#, c-format +msgid "warning from original dump file: %s" +msgstr "asıl dump dosyasından uyarı: %s" + +#: pg_backup_archiver.c:784 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "%s oluşturuluyor \"%s.%s\"" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s\"" +msgstr "%s oluşturuluyor \"%s\"" + +#: pg_backup_archiver.c:844 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "yeni \"%s\" veritabanına bağlanılıyor" + +#: pg_backup_archiver.c:872 +#, c-format +msgid "processing %s" +msgstr "%s işleniyor" + +#: pg_backup_archiver.c:892 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosu için veri işleniyor" + +#: pg_backup_archiver.c:954 +#, c-format +msgid "executing %s %s" +msgstr "%s %s yürütülüyor" + +#: pg_backup_archiver.c:993 +#, c-format +msgid "disabling triggers for %s" +msgstr "%s için tetikleyiciler etkisiz hale getiriliyor" + +#: pg_backup_archiver.c:1019 +#, c-format +msgid "enabling triggers for %s" +msgstr "%s için tetikleyiciler etkinleştiriliyor" + +#: pg_backup_archiver.c:1047 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "iç hata -- WriteData, DataDumper yordamının bağlamı dışında çağrılamaz" + +#: pg_backup_archiver.c:1232 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "seçilen biçimde large-object çıktısı desteklenmemektedir" + +#: pg_backup_archiver.c:1290 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "%d large object geri yüklendi" +msgstr[1] "%d large object geri yüklendi" + +#: pg_backup_archiver.c:1311 pg_backup_tar.c:738 +#, c-format +msgid "restoring large object with OID %u" +msgstr "%u OID'li large-object geri yükleniyor" + +#: pg_backup_archiver.c:1323 +#, c-format +msgid "could not create large object %u: %s" +msgstr "%u large object oluşturulamadı: %s" + +#: pg_backup_archiver.c:1328 pg_dump.c:3463 +#, c-format +msgid "could not open large object %u: %s" +msgstr "%u large object açılamadı: %s" + +#: pg_backup_archiver.c:1385 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "\"%s\" TOC dosyası açılamadı: %m" + +#: pg_backup_archiver.c:1425 +#, c-format +msgid "line ignored: %s" +msgstr "satır yoksayıldı: %s" + +#: pg_backup_archiver.c:1432 +#, c-format +msgid "could not find entry for ID %d" +msgstr "ID %d için bir girdi bulunamıyor" + +#: pg_backup_archiver.c:1453 pg_backup_directory.c:222 +#: pg_backup_directory.c:587 +#, c-format +msgid "could not close TOC file: %m" +msgstr "TOC dosyası kapatılamıyor: %m" + +#: pg_backup_archiver.c:1568 pg_backup_custom.c:159 pg_backup_directory.c:332 +#: pg_backup_directory.c:574 pg_backup_directory.c:637 +#: pg_backup_directory.c:656 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "\"%s\" çıktı dosyası açılamadı: %m" + +#: pg_backup_archiver.c:1570 pg_backup_custom.c:165 +#, c-format +msgid "could not open output file: %m" +msgstr "çıktı dosyası açılamadı: %m" + +#: pg_backup_archiver.c:1663 +#, c-format +msgid "wrote %lu byte of large object data (result = %lu)" +msgid_plural "wrote %lu bytes of large object data (result = %lu)" +msgstr[0] "large object verisinin %lu baytı yazıldı (sonuç = %lu)" +msgstr[1] "large object verisinin %lu baytı yazıldı (sonuç = %lu)" + +#: pg_backup_archiver.c:1668 +#, c-format +msgid "could not write to large object (result: %lu, expected: %lu)" +msgstr "large-object yazılamıyor (sonuç: %lu, beklenen: %lu)" + +#: pg_backup_archiver.c:1760 +#, c-format +msgid "while INITIALIZING:" +msgstr "INITIALIZING sırasında:" + +#: pg_backup_archiver.c:1765 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "PROCESSING TOC sırasında:" + +#: pg_backup_archiver.c:1770 +#, c-format +msgid "while FINALIZING:" +msgstr "FINALIZING sırasında:" + +#: pg_backup_archiver.c:1775 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "TOC girişte hata %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1851 +#, c-format +msgid "bad dumpId" +msgstr "kötü dumpId" + +#: pg_backup_archiver.c:1872 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "TABLE DATA öğesi için kötü tablo dumpId değeri" + +#: pg_backup_archiver.c:1964 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "beklenmeyen veri konum bayrağı %d" + +#: pg_backup_archiver.c:1977 +#, c-format +msgid "file offset in dump file is too large" +msgstr "dump dosyasında dosya göstergesi çok büyük" + +#: pg_backup_archiver.c:2114 pg_backup_archiver.c:2124 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "dizin adı çok uzun: \"%s\"" + +#: pg_backup_archiver.c:2132 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "\"%s\" dizini geçerli bir arşiv olarak görünmüyor (\"toc.dat\" bulunamadı)" + +#: pg_backup_archiver.c:2140 pg_backup_custom.c:176 pg_backup_custom.c:760 +#: pg_backup_directory.c:207 pg_backup_directory.c:391 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "\"%s\" girdi dosyası açılamadı: %m" + +#: pg_backup_archiver.c:2147 pg_backup_custom.c:182 +#, c-format +msgid "could not open input file: %m" +msgstr "girdi dosyası açılamadı: %m" + +#: pg_backup_archiver.c:2153 +#, c-format +msgid "could not read input file: %m" +msgstr "girdi dosyası okuma hatası: %m" + +#: pg_backup_archiver.c:2155 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "girdi dosyası fazla kısa (okunan: %lu, beklenen: 5)" + +#: pg_backup_archiver.c:2240 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "girdi dosyası metin biçiminde bir döküm (dump) gibi görünüyor. Lütfen psql kullanın." + +#: pg_backup_archiver.c:2246 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "girdi dosyası geçerli bir arşiv gibi görünmüyor (çok kısa?)" + +#: pg_backup_archiver.c:2252 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "girdi dosyası geçerli bir arşiv gibi görünmüyor" + +#: pg_backup_archiver.c:2272 +#, c-format +msgid "could not close input file: %m" +msgstr "çıktı dosyası kapatılamadı: %m" + +#: pg_backup_archiver.c:2386 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "tanınmayan dosya biçimi: \"%d\"" + +#: pg_backup_archiver.c:2468 pg_backup_archiver.c:4474 +#, c-format +msgid "finished item %d %s %s" +msgstr "%d %s %s öğesi bitirildi" + +#: pg_backup_archiver.c:2472 pg_backup_archiver.c:4487 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "alt süreç başarısız oldu: çıkış kodu %d" + +#: pg_backup_archiver.c:2592 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "ID %d olan giriş kapsam dışıdır -- bozuk bir TOC olabilir" + +#: pg_backup_archiver.c:2659 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "WITH OIDS ile tanımlanmış tabloların geri yüklenmesi (restore) artık desteklenmemektedir" + +#: pg_backup_archiver.c:2741 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "tanınmayan dil kodlaması \"%s\"" + +#: pg_backup_archiver.c:2746 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "geçersiz ENCODING öğesi: %s" + +#: pg_backup_archiver.c:2764 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "geçersiz STDSTRINGS öğesi: %s" + +#: pg_backup_archiver.c:2789 +#, c-format +msgid "schema \"%s\" not found" +msgstr "\"%s\" şeması bulunamadı" + +#: pg_backup_archiver.c:2796 +#, c-format +msgid "table \"%s\" not found" +msgstr "\"%s\" tablosu bulunamadı" + +#: pg_backup_archiver.c:2803 +#, c-format +msgid "index \"%s\" not found" +msgstr "\"%s\" indeksi bulunamadı" + +#: pg_backup_archiver.c:2810 +#, c-format +msgid "function \"%s\" not found" +msgstr "\"%s\" fonksiyonu bulunamadı" + +#: pg_backup_archiver.c:2817 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "\"%s\" tetikleyicisi bulunamadı" + +#: pg_backup_archiver.c:3196 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "oturum kullanıcısı \"%s\" olarak değiştirilemedi: %s" + +#: pg_backup_archiver.c:3533 pg_backup_archiver.c:3690 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "\"%s\" nesne tipi için sahip bilgisinin nasıl ayarlanacağı bilinmiyor" + +#: pg_backup_archiver.c:3794 +#, c-format +msgid "did not find magic string in file header" +msgstr "dosya başlığında magic string bulunamadı" + +#: pg_backup_archiver.c:3807 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "dosya başlığında desteklenmeyen sürüm (%d.%d)" + +#: pg_backup_archiver.c:3812 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "tamsayı (integer) boyutunda (%lu) tutarlılık kontrolü başarısız" + +#: pg_backup_archiver.c:3816 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "arşiv daha büyük tam sayılara (integer) sahip platformda oluşturulmuş, bazı işlemler başarısız olabilir" + +#: pg_backup_archiver.c:3826 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "dosyada bulunan biçim (%2$d) beklenen biçimden (%1$d) farklıdır" + +#: pg_backup_archiver.c:3842 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "arşiv sıkıştırılmış, ancak bu kurulum sıkıştırmayı desteklemiyor -- uygun veri olmayacak" + +#: pg_backup_archiver.c:3860 +#, c-format +msgid "invalid creation date in header" +msgstr "veri başlığında geçersiz tarih" + +#: pg_backup_archiver.c:3997 +#, c-format +msgid "processing item %d %s %s" +msgstr "%d %s %s öğesi işleniyor" + +#: pg_backup_archiver.c:4076 +#, c-format +msgid "entering main parallel loop" +msgstr "ana paralel döngüye giriliyor" + +#: pg_backup_archiver.c:4087 +#, c-format +msgid "skipping item %d %s %s" +msgstr "%d %s %s öğesi atlanıyor" + +#: pg_backup_archiver.c:4096 +#, c-format +msgid "launching item %d %s %s" +msgstr "%d %s %s öğesi başlatılıyor" + +#: pg_backup_archiver.c:4150 +#, c-format +msgid "finished main parallel loop" +msgstr "ana paralel döngü bitti" + +#: pg_backup_archiver.c:4188 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "atlanan %d %s %s öğesi işleniyor" + +#: pg_backup_archiver.c:4793 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "\"%s\" tablosu oluşturulamadı, onun verileri yüklenmeyecektir" + +#: pg_backup_custom.c:377 pg_backup_null.c:150 +#, c-format +msgid "invalid OID for large object" +msgstr "large object için geçersiz OID" + +#: pg_backup_custom.c:447 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "arşivde ararken tanınmayan veri blok tipine (%d) rastlandı" + +#: pg_backup_custom.c:458 pg_backup_custom.c:818 +#, c-format +msgid "error during file seek: %m" +msgstr "dosya içerisinde gösterge ilerleme hatası: %m" + +#: pg_backup_custom.c:467 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to lack of data offsets in archive" +msgstr "arşivde %d block ID'si bulunamadı -- arşivdeki eksik veri konumu nedeniyle işlenemeyen geçersiz yükleme isteği nedeniyle olabilir" + +#: pg_backup_custom.c:472 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "arşivde %d block ID'si bulunamadı -- aranamayan girdi dosyası nedeniyle işlenemeyen geçersiz yükleme isteği nedeniyle olabilir" + +#: pg_backup_custom.c:477 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "%d blok ID'si arşivde bulunamadı -- arşiv bozulmuş olabilir" + +#: pg_backup_custom.c:484 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "veriyi okurken beklenmeyen blok ID (%d) bulundu -- beklenen: %d" + +#: pg_backup_custom.c:498 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "arşivi yüklerken bilinmeyen veri blok tipi %d bulundu" + +#: pg_backup_custom.c:580 +#, c-format +msgid "could not read from input file: %m" +msgstr "girdi dosyası okuma hatası: %m" + +#: pg_backup_custom.c:698 pg_backup_custom.c:751 pg_backup_custom.c:891 +#: pg_backup_tar.c:1091 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "arşiv dosyasında arama pozisyonu belirlenemedi: %m" + +#: pg_backup_custom.c:715 pg_backup_custom.c:755 +#, c-format +msgid "could not close archive file: %m" +msgstr "arşiv dosyası kapatma hatası: %m" + +#: pg_backup_custom.c:738 +#, c-format +msgid "can only reopen input archives" +msgstr "sadece girdi arşivleri tekrar açılabilir" + +#: pg_backup_custom.c:745 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "standart girdiden paralel geri yükleme desteklenmiyor" + +#: pg_backup_custom.c:747 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "taranamayan dosyadan paralel geri yükleme desteklenmiyor" + +#: pg_backup_custom.c:763 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "arşiv dosyasında arama pozisyonu ayarlanamadı: %m" + +#: pg_backup_custom.c:839 +#, c-format +msgid "compressor active" +msgstr "sıkıştırma etkin" + +#: pg_backup_custom.c:894 +#, c-format +msgid "ftell mismatch with expected position -- ftell used" +msgstr "ftell fonksiyonun bidirdiği pozisyonu ile beklenen pozisyon uyumsuz -- ftell kullanıldı" + +#: pg_backup_db.c:44 +#, c-format +msgid "could not get server_version from libpq" +msgstr "libpq kütüphanesinden server_version alınamadı" + +#: pg_backup_db.c:55 pg_dumpall.c:1806 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "sunucu sürümü: %s; %s sürümü: %s" + +#: pg_backup_db.c:57 pg_dumpall.c:1808 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "sunucu sürümü uyuşmazlığı nedeniyle iptal ediliyor (abort)" + +#: pg_backup_db.c:140 +#, c-format +msgid "connecting to database \"%s\" as user \"%s\"" +msgstr "\"%2$s\" kullanıcısı olarak \"%1$s\" veritabanına bağlanılıyor" + +#: pg_backup_db.c:147 pg_backup_db.c:196 pg_backup_db.c:257 pg_backup_db.c:298 +#: pg_dumpall.c:1631 pg_dumpall.c:1744 +msgid "Password: " +msgstr "Parola: " + +#: pg_backup_db.c:179 +#, c-format +msgid "failed to reconnect to database" +msgstr "veritabanına yeniden bağlanma hatası" + +#: pg_backup_db.c:184 +#, c-format +msgid "could not reconnect to database: %s" +msgstr "%s veritabanına yeniden bağlanılamadı" + +#: pg_backup_db.c:200 +#, c-format +msgid "connection needs password" +msgstr "bağlantı parola gerektiriyor" + +#: pg_backup_db.c:251 +#, c-format +msgid "already connected to a database" +msgstr "bir veritabanına zaten bağlı" + +#: pg_backup_db.c:290 +#, c-format +msgid "failed to connect to database" +msgstr "veritabanına bağlantı başarısız oldu" + +#: pg_backup_db.c:306 +#, c-format +msgid "connection to database \"%s\" failed: %s" +msgstr "\"%s\" veritabanına bağlantı başarısız oldu: %s" + +#: pg_backup_db.c:378 pg_dumpall.c:1664 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:385 pg_dumpall.c:1869 pg_dumpall.c:1892 +#, c-format +msgid "query failed: %s" +msgstr "sorgu başarısız oldu: %s" + +#: pg_backup_db.c:387 pg_dumpall.c:1870 pg_dumpall.c:1893 +#, c-format +msgid "query was: %s" +msgstr "sorgu şu idi: %s" + +#: pg_backup_db.c:428 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "sorgu 1 yerine %d satır döndürdü: %s" +msgstr[1] "sorgu 1 yerine %d satır döndürdü: %s" + +#: pg_backup_db.c:520 pg_backup_db.c:594 pg_backup_db.c:601 +msgid "could not execute query" +msgstr "sorgu çalıştırılamadı" + +#: pg_backup_db.c:573 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "PQputCopyData'nın döndürdüğü hata: %s" + +#: pg_backup_db.c:622 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "PQputCopyEnd'in döndürdüğü hata: %s" + +#: pg_backup_db.c:634 pg_dump.c:1924 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "\"%s\" tablosunun COPY işlemi sırasında beklenmeyen ilave sonuçlar" + +#: pg_backup_db.c:646 +msgid "could not start database transaction" +msgstr "veritabanı transaction'u başlatılamadı" + +#: pg_backup_db.c:654 +msgid "could not commit database transaction" +msgstr "veritabanı işlemi (transaction) commit edilemedi" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "herhangi bir çıktı dizini belirtilmedi" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" dizini okunamıyor: %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "\"%s\" dizini kapatılamadı: %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "\"%s\" dizini oluşturulamadı: %m" + +#: pg_backup_directory.c:350 pg_backup_directory.c:488 +#: pg_backup_directory.c:518 +#, c-format +msgid "could not write to output file: %s" +msgstr "çıktı dosyasına yazma başarısız: %s" + +#: pg_backup_directory.c:403 +#, c-format +msgid "could not close data file: %m" +msgstr "veri dosyası kapatılamadı: %m" + +#: pg_backup_directory.c:443 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "girdi için \"%s\" large object TOC dosyası açılamadı: %m" + +#: pg_backup_directory.c:454 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "\"%s\" large object TOC dosyasında geçersiz satır: \"%s\"" + +#: pg_backup_directory.c:463 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "\"%s\" large object TOC dosyası okuma hatası" + +#: pg_backup_directory.c:467 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "\"%s\" large object TOC dosyası kapatılamadı: %m" + +#: pg_backup_directory.c:678 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "blobs TOC dosyası yazma hatası" + +#: pg_backup_directory.c:710 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "dosya adı çok uzun: \"%s\"" + +#: pg_backup_null.c:75 +#, c-format +msgid "this format cannot be read" +msgstr "bu biçim okunamıyor" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "çıktı için \"%s\" TOC dosyası açılamadı: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "çıktı için TOC dosyası açılamadı: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:358 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "sıkıştırma, tar çıktı formatı tarafından desteklenmiyor" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "\"%s\" TOC dosyası girdi için açılamadı: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "girdi için TOC dosyası açılamadı: %m" + +#: pg_backup_tar.c:344 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "\"%s\" dosyası arşivde bulunamadı" + +#: pg_backup_tar.c:410 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "geçici dosya adı oluşturulamadı: %m" + +#: pg_backup_tar.c:421 +#, c-format +msgid "could not open temporary file" +msgstr "geçici dosya açılamadı" + +#: pg_backup_tar.c:448 +#, c-format +msgid "could not close tar member" +msgstr "tar öğesi kapatılamadı" + +#: pg_backup_tar.c:571 +#, c-format +msgid "internal error -- neither th nor fh specified in tarReadRaw()\n" +msgstr "iç hata - th ya da fh, tarReadRaw() içinde belirtilmedi\n" + +#: pg_backup_tar.c:693 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "beklenmeyen COPY ifadesi söz dizimi: \"%s\"" + +#: pg_backup_tar.c:961 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "(%u) large object'i için geçersiz OID" + +#: pg_backup_tar.c:1106 +#, c-format +msgid "could not close temporary file: %m" +msgstr "geçici dosya kapatma hatası: %m" + +#: pg_backup_tar.c:1115 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "gerçek dosya uzunluğu (%s) beklenen uzunluğu (%s) ile uyuşmamaktadır" + +#: pg_backup_tar.c:1172 pg_backup_tar.c:1202 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "tar arşivinde \"%s\" dosyası için başlık bulunamadı" + +#: pg_backup_tar.c:1190 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "bu arşiv biçiminde veriyi sıra dışı geri yükleme desteklenmemektedir: \"%s\" bekleniyor ancak arşiv dosyasında %s ondan önce gelmektedir." + +#: pg_backup_tar.c:1235 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "eksik tar başlığı bulundu (%lu bayt)" +msgstr[1] "eksik tar başlığı bulundu (%lu bayt)" + +#: pg_backup_tar.c:1286 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "%s dosyasında bozuk tar başlığı (beklenen: %d, hesaplanan: %d) dosya pozisyonu %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "bilinmeyen bölüm adı: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:612 pg_dump.c:629 pg_dumpall.c:338 +#: pg_dumpall.c:348 pg_dumpall.c:357 pg_dumpall.c:366 pg_dumpall.c:374 +#: pg_dumpall.c:388 pg_dumpall.c:464 pg_restore.c:290 pg_restore.c:306 +#: pg_restore.c:324 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Daha fazla bilgi için \"%s --help\" yazabilirsiniz.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "on_exit_nicely slotları yetersiz" + +#: pg_dump.c:543 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "sıkıştırma seviyesi 0..9 aralığında olmalı" + +#: pg_dump.c:581 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits -15..3 aralığında olmalı" + +#: pg_dump.c:604 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert %d..%d aralığında olmalı" + +#: pg_dump.c:627 pg_dumpall.c:346 pg_restore.c:304 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "çok fazla komut satırı argümanı (ilki \"%s\")" + +#: pg_dump.c:648 pg_restore.c:333 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "-s/--schema-only ve -a/--data-only seçenekleri aynı anda kullanılamazlar" + +#: pg_dump.c:654 pg_restore.c:339 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "-c/--clean ve -a/--data-only seçenekleri aynı anda kullanılamazlar" + +#: pg_dump.c:659 pg_dumpall.c:381 pg_restore.c:388 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "--if-exists seçeneği -c/--clean seçeneğini gerektirir" + +#: pg_dump.c:666 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert or --column-inserts" +msgstr "--on-conflict-do-nothing seçeneği --inserts, --rows-per-insert veya --column-inserts seçeneğini gerektirir" + +#: pg_dump.c:688 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "istenen sıkıştırma bu kurulumda desteklenmemektedir -- arşiv sıkıştırılmayacak" + +#: pg_dump.c:709 pg_restore.c:355 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "geçersiz sayıda parallel iş" + +#: pg_dump.c:713 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "paralel yedek sadece dizin biçimi tarafından destekleniyor" + +#: pg_dump.c:768 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Senkronize anlık görüntüler (snapshot) bu sunucu sürümü tarafından desteklenmiyor.\n" +"Senkronize anlık görüntülere ihtiyaç yoksa bunun yerine --no-synchronized-snapshots \n" +"ile çalıştırın." + +#: pg_dump.c:774 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Bu sunucu sürümünde dışa aktarılmış anlık görüntü (exported snapshot) desteklenmemektedir." + +#: pg_dump.c:786 +#, c-format +msgid "last built-in OID is %u" +msgstr "son gömülü OID : %u" + +#: pg_dump.c:795 +#, c-format +msgid "no matching schemas were found" +msgstr "uygun şema bulunamadı" + +#: pg_dump.c:809 +#, c-format +msgid "no matching tables were found" +msgstr "uygun tablo bulunamadı" + +#: pg_dump.c:981 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s veritabanını metin dosyası ya da diğer biçimlerde dump eder.\n" +"\n" + +#: pg_dump.c:982 pg_dumpall.c:617 pg_restore.c:468 +#, c-format +msgid "Usage:\n" +msgstr "Kullanımı:\n" + +#: pg_dump.c:983 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [SEÇENEK]... [VERİTABANI_ADI]\n" + +#: pg_dump.c:985 pg_dumpall.c:620 pg_restore.c:471 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"Genel seçenekler:\n" + +#: pg_dump.c:986 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=DOSYAADI çıktı dosya adı ya da dizin adı\n" + +#: pg_dump.c:987 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p çıktı dosya biçimi (c:özel, d:dizin, t:tar,\n" +" p: düz metin (varsayılan))\n" +"\n" + +#: pg_dump.c:989 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=SAYI döküm (dump) için belirtilen sayı kadar paralel süreç kullan\n" + +#: pg_dump.c:990 pg_dumpall.c:622 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose detaylı açıklamalı mod\n" + +#: pg_dump.c:991 pg_dumpall.c:623 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version sürüm bilgisini göster, sonra çık\n" + +#: pg_dump.c:992 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 sıkıştırılmış biçimler için sıkıştırma seviyesi\n" + +#: pg_dump.c:993 pg_dumpall.c:624 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=ZAMANAŞIMI tablo kilitlemesi için ZAMANAŞIMI kadar bekledikten sonra hata ver\n" + +#: pg_dump.c:994 pg_dumpall.c:652 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr "" +" --no-sync değişikliklerin diske yazılması için bekleme\n" +"\n" + +#: pg_dump.c:995 pg_dumpall.c:625 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help bu yardımı gösterir ve sonra çıkar\n" + +#: pg_dump.c:997 pg_dumpall.c:626 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"Çıktı içeriğini kontrol eden seçenekler:\n" + +#: pg_dump.c:998 pg_dumpall.c:627 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only sadece veriyi yedekle (dump); şemayı yedekleme\n" + +#: pg_dump.c:999 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs yedeğin (dump) içine büyük nesneleri dahil et\n" + +#: pg_dump.c:1000 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs büyük nesneleri yedeğin içine dahil etme\n" + +#: pg_dump.c:1001 pg_restore.c:482 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean veritabanı nesnelerini yeniden oluşturmadan önce temizle (kaldır)\n" + +#: pg_dump.c:1002 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create yedeğin (dump) içine veritabanını oluşturacak komutları da ekle\n" + +#: pg_dump.c:1003 pg_dumpall.c:629 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=DİLKODLAMASI veriyi DİLKODLAMASI dil kodlamasıyla yedekle\n" + +#: pg_dump.c:1004 +#, c-format +msgid " -n, --schema=SCHEMA dump the named schema(s) only\n" +msgstr " -n, --schema=ŞEMA sadece belirtilen şema veya şemaları yedekle\n" + +#: pg_dump.c:1005 +#, c-format +msgid " -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n" +msgstr " -N, --exclude-schema=ŞEMA bu şema veya şemaları yedekleme\n" + +#: pg_dump.c:1006 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr "" +" -O, --no-owner düz metin biçiminde nesne \n" +" sahipliğinin yüklenmesini atla\n" + +#: pg_dump.c:1008 pg_dumpall.c:634 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only sadece şemayı yedekle (dump), veriyi değil\n" + +#: pg_dump.c:1009 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=İSİM düz metin formatında kullanılacak superuser kullanıcı adı\n" + +#: pg_dump.c:1010 +#, c-format +msgid " -t, --table=TABLE dump the named table(s) only\n" +msgstr " -t, --table=TABLO sadece ismi geçen tablo veya tabloları yedekle\n" + +#: pg_dump.c:1011 +#, c-format +msgid " -T, --exclude-table=TABLE do NOT dump the named table(s)\n" +msgstr " -T, --exclude-table=TABLO ismi geçen tablo veya tabloları yedekleme\n" + +#: pg_dump.c:1012 pg_dumpall.c:637 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges yetkileri yedekleme (grant/revoke)\n" + +#: pg_dump.c:1013 pg_dumpall.c:638 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade sadece yükseltme araçlarının kullanımı için\n" + +#: pg_dump.c:1014 pg_dumpall.c:639 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts veriyi kolon adları ile INSERT komutları olarak yedekle\n" + +#: pg_dump.c:1015 pg_dumpall.c:640 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr " --disable-dollar-quoting dollar quoting kullanmayı engelle, standart SQL quoting kullan\n" + +#: pg_dump.c:1016 pg_dumpall.c:641 pg_restore.c:499 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers salt-veri geri yüklemesi sırasında tetikleyicileri devre dışı bırak\n" + +#: pg_dump.c:1017 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr "" +" --enable-row-security satır güvenliğini etkinleştir (sadece kullanıcının erişimi\n" +" olan içeriği yedekle)\n" + +#: pg_dump.c:1019 +#, c-format +msgid " --exclude-table-data=TABLE do NOT dump data for the named table(s)\n" +msgstr " --exclude-table-data=TABLO bu tablo veya tabloları yedekleme\n" + +#: pg_dump.c:1020 pg_dumpall.c:643 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM extra_float_digits için varayılan ayarı geçersiz kıl\n" + +#: pg_dump.c:1021 pg_dumpall.c:644 pg_restore.c:501 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists nesneleri silerken IF EXISTS kullan\n" + +#: pg_dump.c:1022 pg_dumpall.c:645 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr "" +" --inserts veriyi COPY'den ziyade INSERT komutları olarak yedekle\n" +"\n" + +#: pg_dump.c:1023 pg_dumpall.c:646 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root bölümleri (partition) kök tablo üzerinden yükle\n" + +#: pg_dump.c:1024 pg_dumpall.c:647 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr "" +" --no-comments açıklamaları (comments) yedekleme\n" +"\n" + +#: pg_dump.c:1025 pg_dumpall.c:648 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications yayınları yedekleme\n" + +#: pg_dump.c:1026 pg_dumpall.c:650 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels güvenlik etiketi atamalarını yedekleme\n" + +#: pg_dump.c:1027 pg_dumpall.c:651 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions abonelikleri yedekleme\n" + +#: pg_dump.c:1028 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots paralel işlerde senkronize anlık görüntüleri yedekleme\n" + +#: pg_dump.c:1029 pg_dumpall.c:653 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces tablespace atamalarını yedekleme\n" + +#: pg_dump.c:1030 pg_dumpall.c:654 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data loglanmayan tablo verisini yedekleme\n" + +#: pg_dump.c:1031 pg_dumpall.c:655 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing INSERT komutlarına ON CONFLICT DO NOTHING ekle\n" + +#: pg_dump.c:1032 pg_dumpall.c:656 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers anahtar sözcükler olmasa bile tüm belirteçleri çift tırnak içine al\n" + +#: pg_dump.c:1033 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS INSERT başına satır sayısı; --inserts seçeneğiyle kullanılır\n" + +#: pg_dump.c:1034 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=BÖLÜM belirtilen bölümü yedekle (pre-data, data, veya post-data)\n" + +#: pg_dump.c:1035 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable yedeğin bir anormallik olmadan biteceği ana kadar bekle\n" + +#: pg_dump.c:1036 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT yedek için verilen anlık görüntüyü (snapshot) kullan\n" + +#: pg_dump.c:1037 pg_restore.c:510 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr "" +" --strict-names tablo ve/veya şema her biri en az bir varlıkla (entity)\n" +" eşleşecek desenler (pattern) bulundurmalıdır\n" + +#: pg_dump.c:1039 pg_dumpall.c:657 pg_restore.c:512 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" Sahipliği ayarlamak için ALTER OWNER komutları yerine\n" +" SET SESSION AUTHORIZATION komutlarını kullan\n" + +#: pg_dump.c:1043 pg_dumpall.c:661 pg_restore.c:516 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"Bağlantı Seçenekleri:\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=VERİTABANI_ADI yedeklenecek veritabanı adı\n" + +#: pg_dump.c:1045 pg_dumpall.c:663 pg_restore.c:517 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME veritabanı sunucusu adresi ya da soket dizini\n" + +#: pg_dump.c:1046 pg_dumpall.c:665 pg_restore.c:518 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p PORT veritabanı sunucusunun port numarası\n" + +#: pg_dump.c:1047 pg_dumpall.c:666 pg_restore.c:519 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=KULLANICI_ADI bağlanılacak kullanıcı adı\n" + +#: pg_dump.c:1048 pg_dumpall.c:667 pg_restore.c:520 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password bağlanmak için kesinlikle parola sorma\n" + +#: pg_dump.c:1049 pg_dumpall.c:668 pg_restore.c:521 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W şifre sor (otomatik olarak her zaman açık)\n" + +#: pg_dump.c:1050 pg_dumpall.c:669 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROL ADI yedek işleminden önce SET ROLE çalıştır\n" + +#: pg_dump.c:1052 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"Veritabanı adı verilmemişse PGDATABASE çevre değişkeni\n" +"kullanılacaktır.\n" +"\n" + +#: pg_dump.c:1054 pg_dumpall.c:673 pg_restore.c:528 +#, c-format +msgid "Report bugs to .\n" +msgstr "Hataları adresine bildirin.\n" + +#: pg_dump.c:1073 pg_dumpall.c:499 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "belirtilen \"%s\" istemci dil kodlaması geçersiz" + +#: pg_dump.c:1218 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"Yedek (standby) sunucularda anlık görüntüler (snapshot) bu sunucu sürümünde desteklenmiyor.\n" +"Senkronize anlık görüntülere ihtiyaç yoksa bunun yerine --no-synchronized-snapshots\n" +"ile çalıştırın." + +#: pg_dump.c:1287 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "geçersiz çıktı biçimi \"%s\" belirtildi" + +#: pg_dump.c:1325 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "\"%s\" şablonu (pattern) için eşleşen şema bulunamadı" + +#: pg_dump.c:1390 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "\"%s\" şablonu (pattern) için eşleşen tablo bulunamadı" + +#: pg_dump.c:1804 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun içeriği yedekleniyor" + +#: pg_dump.c:1905 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "\"%s\" tablosunu içeriğinin yedeklenmesi başarısız: PQgetCopyData() başarısız." + +#: pg_dump.c:1906 pg_dump.c:1916 +#, c-format +msgid "Error message from server: %s" +msgstr "Sunucudan hata mesajı alındı: %s" + +#: pg_dump.c:1907 pg_dump.c:1917 +#, c-format +msgid "The command was: %s" +msgstr "O sırada yürütülen komut: %s" + +#: pg_dump.c:1915 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "\"%s\" tablosunun içeriğinin yedeklenmesi başarısız: PQgetResult() başarısız." + +#: pg_dump.c:2669 +#, c-format +msgid "saving database definition" +msgstr "veritabanın tanımı kaydediliyor" + +#: pg_dump.c:3116 +#, c-format +msgid "saving encoding = %s" +msgstr "dil kodlaması kaydediliyor = %s" + +#: pg_dump.c:3143 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "standard_conforming_strings kaydediliyor = %s " + +#: pg_dump.c:3184 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "current_schemas() sonucu ayrıştırılamadı" + +#: pg_dump.c:3203 +#, c-format +msgid "saving search_path = %s" +msgstr "search_path = %s olarak kaydediliyor" + +#: pg_dump.c:3245 +#, c-format +msgid "reading large objects" +msgstr "large object'ler okunuyor" + +#: pg_dump.c:3427 +#, c-format +msgid "saving large objects" +msgstr "large object'ler kaydediliyor" + +#: pg_dump.c:3473 +#, c-format +msgid "error reading large object %u: %s" +msgstr "%u large object okurken hata oldu: %s" + +#: pg_dump.c:3525 +#, c-format +msgid "reading row security enabled for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosu için etkinleştirilen satır güvenliği (row security) okunuyor" + +#: pg_dump.c:3556 +#, c-format +msgid "reading policies for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosu için ilkeler (policy) okunuyor" + +#: pg_dump.c:3707 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "beklenmeyen ilke (policy) komut türü: %c" + +#: pg_dump.c:3834 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "\"%s\" fonksiyonunun sahibi geçersiz görünüyor" + +#: pg_dump.c:3971 +#, c-format +msgid "reading publication membership for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun yayın (publication) üyeliği okunuyor" + +#: pg_dump.c:4116 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "abonelikler yedeklenmedi çünkü geçerli kullanıcı superuser değil" + +#: pg_dump.c:4170 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "\"%s\" aboneliğinin sahibi geçersiz görünüyor" + +#: pg_dump.c:4214 +#, c-format +msgid "could not parse subpublications array" +msgstr "alt-yayınlar dizisi ayrıştırılamadı" + +#: pg_dump.c:4486 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "%s için üst uzantı bulunamadı %s" + +#: pg_dump.c:4618 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "\"%s\" şemasının sahibi geçersiz görünüyor" + +#: pg_dump.c:4641 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "%u OID'li şema mevcut değil" + +#: pg_dump.c:4966 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "\"%s\" veri tipinin sahibi geçersiz görünüyor" + +#: pg_dump.c:5051 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "\"%s\" operatörünün sahibi geçersiz görünüyor" + +#: pg_dump.c:5353 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "\"%s\" operatör sınıfının sahibi geçersiz görünüyor" + +#: pg_dump.c:5437 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "\"%s\" operatör ailesinin sahibi geçersiz görünüyor" + +#: pg_dump.c:5606 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "\"%s\" aggregate fonksiyonun sahibi geçersiz görünüyor" + +#: pg_dump.c:5866 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "\"%s\" fonksiyonunun sahibi geçersiz görünüyor" + +#: pg_dump.c:6662 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "\"%s\" tablosunun sahibi geçersiz görünüyor" + +#: pg_dump.c:6704 pg_dump.c:17053 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "tutarlılık kontrolü başarısız, %2$u OID'li dizinin (sequence) %1$u OID'li üst tablosu bulunamadı" + +#: pg_dump.c:6848 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun indeksleri okunuyor" + +#: pg_dump.c:7249 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun foreign key bütünlük kısıtlamaları okunuyor" + +#: pg_dump.c:7468 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "tutarlılık kontrolü başarısız, %2$u OID'li pg_rewrite girdisinin %1$u OID'li üst tablosu bulunamadı" + +#: pg_dump.c:7551 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun tetikleyicileri okunuyor" + +#: pg_dump.c:7684 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "sorgu, \"%2$s\" tablosu (tablo OID: %3$u) üzerindeki \"%1$s\" foreign key tetikleyici için null referans edilen tablo adı getirdi" + +#: pg_dump.c:8239 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "\"%s.%s\" tablosunun sütunları ve tipleri bulunuyor" + +#: pg_dump.c:8375 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "\"%s\" tablosunda geçersiz sütun numaralandırması" + +#: pg_dump.c:8412 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "\"%s.%s\" tablosu için varsayılan ifadeler bulunuyor" + +#: pg_dump.c:8434 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "\"%2$s\" tablosu için geçersiz adnum değeri %1$d" + +#: pg_dump.c:8499 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "\"%s.%s\" tablosu için kontrol kısıtlamaları bulunuyor" + +#: pg_dump.c:8548 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "%d check kısıtlamasının \"%s\" tablosunda bulunması beklendi; ancak %d bulundu" +msgstr[1] "%d check kısıtlamasının \"%s\" tablosunda bulunması beklendi; ancak %d bulundu" + +#: pg_dump.c:8552 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Sistem kataloğu bozulmuş olabilir.)" + +#: pg_dump.c:10140 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "\"%s\" veri tipinin typtype'i geçersiz görünüyor" + +#: pg_dump.c:11496 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "proargnames dizisi içinde belirsiz değer" + +#: pg_dump.c:11868 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "proallargtypes dizisi ayrıştırılamadı" + +#: pg_dump.c:11884 +#, c-format +msgid "could not parse proargmodes array" +msgstr "proargmodes dizisi ayrıştırılamadı" + +#: pg_dump.c:11898 +#, c-format +msgid "could not parse proargnames array" +msgstr "proargnames dizisi ayrıştırılamadı" + +#: pg_dump.c:11909 +#, c-format +msgid "could not parse proconfig array" +msgstr "proconfig dizisi ayrıştırılamadı" + +#: pg_dump.c:11989 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "\"%s\" fonksiyonu için bilinmeyen provolatile değeri" + +#: pg_dump.c:12039 pg_dump.c:14094 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "unrecognized proparallel value for function \"%s\"" + +#: pg_dump.c:12172 pg_dump.c:12282 pg_dump.c:12289 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "%u OID'li fonksiyon için fonksiyon tanımı bulunamadı" + +#: pg_dump.c:12211 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "pg_cast.castfunc veya pg_cast.castmethod field alanı içinde belirsiz değer" + +#: pg_dump.c:12214 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "pg_cast.castmethod field alanı içinde belirsiz değer" + +#: pg_dump.c:12308 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "belirsiz dönüşüm tanımı, trffromsql ve trftosql'in en azından biri sıfırdan farklı olmalı" + +#: pg_dump.c:12325 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "pg_transform.trffromsql alanı içinde belirsiz değer" + +#: pg_dump.c:12346 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "pg_transform.trftosql alanı içinde belirsiz değer" + +#: pg_dump.c:12663 +#, c-format +msgid "could not find operator with OID %s" +msgstr "%s OID'li olan operatör bulunamadı" + +#: pg_dump.c:12731 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "\"%2$s\" erişim yöntemi için geçersiz tip \"%1$c\"" + +#: pg_dump.c:13486 +#, c-format +msgid "unrecognized collation provider: %s\n" +msgstr "bilinmeyen karşılaştırma (collation) sağlayıcısı: %s\n" + +#: pg_dump.c:13958 +#, c-format +msgid "aggregate function %s could not be dumped correctly for this database version; ignored" +msgstr "%s aggregate fonksiyonu veritabanının bu sürümünde düzgün dump edilemiyor; atlanıyor" + +#: pg_dump.c:14013 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "\"%s\" toplamı (aggregate) için tanınmayan aggfinalmodify değeri" + +#: pg_dump.c:14069 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "\"%s\" toplamı (aggregate) için tanınmayan aggmfinalmodify değeri" + +#: pg_dump.c:14793 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "öntanımlı yetkilerde bilinmeyen nesne tipi: %d" + +#: pg_dump.c:14811 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "öntanımlı ACL listesi ayrıştırılamıyor (%s)" + +#: pg_dump.c:14892 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "\"%3$s\" nesnesinin ilk GRANT ACL listesi (%1$s) veya ilk REVOKE ACL listesi (%2$s) ayrıştırılamıyor (%4$s)" + +#: pg_dump.c:14900 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "\"%3$s\" nesnesinin GRANT ACL listesi (%1$s) veya REVOKE ACL listesi (%2$s) ayrıştırılamıyor (%4$s)" + +#: pg_dump.c:15402 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "\"%s\" view tanımını getirecek sorgu hiçbir veri getirmedi" + +#: pg_dump.c:15405 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "\"%s\" view tanımını getirecek sorgu birden çok tanım getirdi" + +#: pg_dump.c:15412 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "\"%s\" view tanımı boş görünüyor (uzunluğu sıfır)" + +#: pg_dump.c:15494 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS artık desteklenmiyor (\"%s\" tablosu)" + +#: pg_dump.c:15945 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "\"%2$s\" tablosu için geçersiz üst nesne sayısı %1$d" + +#: pg_dump.c:16282 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "\"%2$s\" tablosu için geçersiz sütun sayısı %1$d" + +#: pg_dump.c:16546 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "\"%s\" bütünlük kısıtlamasının indeksi eksik" + +#: pg_dump.c:16766 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "bilinmeyen bütünlük kısıtlama türü: %c" + +#: pg_dump.c:16898 pg_dump.c:17119 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "\"%s\" sequence verisini getirecek sorgu %d satır döndürdü (bir satır bekleniyordu)" +msgstr[1] "\"%s\" sequence verisini getirecek sorgu %d satır döndürdü (bir satır bekleniyordu)" + +#: pg_dump.c:16932 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "tanınmayan sequence tipi \"%s\"" + +#: pg_dump.c:17216 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "beklenmeyen tgtype değeri: %d" + +#: pg_dump.c:17290 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "\"%3$s\" tablosunun \"%2$s\" tetikleyicisi için geçersiz argüman dizesi (%1$s)" + +#: pg_dump.c:17519 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "\"%s\" tablosundan \"%s\" rule'unu getiren sorgu başarısız: dönen satır sayısı yanlış" + +#: pg_dump.c:17681 +#, c-format +msgid "could not find referenced extension %u" +msgstr "referans verilen uzantı bulunamadı %u" + +#: pg_dump.c:17893 +#, c-format +msgid "reading dependency data" +msgstr "bağımlılık verileri okunuyor" + +#: pg_dump.c:17948 +#, c-format +msgid "no referencing object %u %u" +msgstr "referans veren nesne yok %u %u" + +#: pg_dump.c:17959 +#, c-format +msgid "no referenced object %u %u" +msgstr "referans verilen nesne yok %u %u" + +#: pg_dump.c:18327 +#, c-format +msgid "could not parse reloptions array" +msgstr "reloptions dizisi (array) ayrıştırılamadı" + +#: pg_dump_sort.c:328 +#, c-format +msgid "invalid dumpId %d" +msgstr "geçersiz dumpId %d" + +#: pg_dump_sort.c:334 +#, c-format +msgid "invalid dependency %d" +msgstr "geçersiz bağımlılık %d" + +#: pg_dump_sort.c:567 +#, c-format +msgid "could not identify dependency loop" +msgstr "bağımlılık döngüsü tespit edilemedi" + +#: pg_dump_sort.c:1130 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "DİKKAT: Bu tablo üzerinde dairesel (circular) foreign-key kısıtlamaları bulunmaktadır:" +msgstr[1] "DİKKAT: Bu tablolar arasında dairesel (circular) foreign-key kısıtlamaları bulunmaktadır:" + +#: pg_dump_sort.c:1134 pg_dump_sort.c:1154 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1135 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "--disable-triggers kullanmadan veya kısıtlamaları (constraint) geçici olarak kaldırmadan yedeği (dump) geri yükleyemebilirsiniz." + +#: pg_dump_sort.c:1136 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Bu sorunla karşılaşmamak için --data-only yedek yerine tam yedek (full dump) almayı düşünün." + +#: pg_dump_sort.c:1148 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "bu öğeler arasındaki bağımlılık döngüsü çözülemedi" + +#: pg_dumpall.c:200 +#, c-format +msgid "" +"The program \"pg_dump\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"\"pg_dump\" uygulaması %s için gerekmektedir ancak\n" +"\"%s\" ile aynı dizinde bulunamadı.\n" +"Kurulumunuzu kontrol edin." + +#: pg_dumpall.c:205 +#, c-format +msgid "" +"The program \"pg_dump\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"\"pg_dump\" uygulaması \"%s\" tarafından bulundu\n" +"ancak %s ile aynı sürüm değildir.\n" +"Kurulumunuzu kontrol edin." + +#: pg_dumpall.c:356 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only or -t/--tablespaces-only" +msgstr "--exclude-database seçeneği -g/--globals-only, -r/--roles-only veya -t/--tablespaces-only ile birlikte kullanılamaz" + +#: pg_dumpall.c:365 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "-g/--globals-only ve -r/--roles-only seçenekleri beraber kullanılamaz" + +#: pg_dumpall.c:373 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "-g/--globals-only ve -t/--tablespaces-only seçenekleri beraber kullanılamaz" + +#: pg_dumpall.c:387 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "-r/--roles-only ve -t/--tablespaces-only seçenekleri birlikte kullanılamaz" + +#: pg_dumpall.c:448 pg_dumpall.c:1734 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "\"%s\" veritabanına bağlanılamadı" + +#: pg_dumpall.c:462 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"\"postgres\" veya \"template1\" veritabanına bağlanılamadı\n" +"Lütfen alternatif bir veritabanı belirtin" + +#: pg_dumpall.c:484 +#, c-format +msgid "could not open the output file \"%s\": %m" +msgstr "\"%s\" çıktı dosyası açılamadı: %m" + +#: pg_dumpall.c:616 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s, PostgreSQL veritabanı clusteri SQL betik dosyasına aktarıyor.\n" +"\n" + +#: pg_dumpall.c:618 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [SEÇENEK]...\n" + +#: pg_dumpall.c:621 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=DOSYA_ADI çıktı dosya adı\n" + +#: pg_dumpall.c:628 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean yeniden oluşturmadan önce veritabanlarını temizle (drop)\n" + +#: pg_dumpall.c:630 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only Sadece global nesneleri yedekle, veritabanlarını yedekleme\n" + +#: pg_dumpall.c:631 +#, c-format +msgid " -o, --oids include OIDs in dump\n" +msgstr " -o, --oids yedeğin içine OID'leri de ekle\n" + +#: pg_dumpall.c:632 pg_restore.c:491 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner veri sahipliği ile ilgili bilgileri geri yükleme\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only sadece rolleri yedekle, veritabanlarını ya da tablespace'leri değil\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=AD yedeklerde kullanılacak superuser kullanıcı adı\n" + +#: pg_dumpall.c:636 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only sadece tablespaceleri yedekle, veritabanlarını ya da rolleri değil\n" + +#: pg_dumpall.c:642 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=DESEN isimleri DESEN ile eşleşen veritabanlarını hariç tut\n" + +#: pg_dumpall.c:649 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " -W, --password rollerin parolalarını yedekleme\n" + +#: pg_dumpall.c:662 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR bağlantı cümleciğini kullanarak bağlan\n" + +#: pg_dumpall.c:664 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=VERİTABANI ADI varsayılan alternatif veritabanı\n" + +#: pg_dumpall.c:671 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"Eğer -f/--file kullanılmazsa, SQL betiği standart çıktıya\n" +"yazılacaktır.\n" +"\n" + +#: pg_dumpall.c:876 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "\"pg_\" ile başlayan rol adı atlandı (%s)" + +#: pg_dumpall.c:1258 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "\"%2$s\" tablespace için ACL (%1$s) listesi ayrıştırılamadı" + +#: pg_dumpall.c:1475 +#, c-format +msgid "excluding database \"%s\"..." +msgstr "\"%s\" veritabanı hariç tutuluyor..." + +#: pg_dumpall.c:1479 +#, c-format +msgid "dumping database \"%s\"..." +msgstr "\"%s\" veritabanı dökümü alınıyor(dump)..." + +#: pg_dumpall.c:1511 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump \"%s\" veritabanında başarısız oldu, çıkılıyor" + +#: pg_dumpall.c:1520 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "\"%s\" çıktı dosyası yeniden açılamadı: %m" + +#: pg_dumpall.c:1564 +#, c-format +msgid "running \"%s\"" +msgstr "\"%s\" yürütülüyor" + +#: pg_dumpall.c:1755 +#, c-format +msgid "could not connect to database \"%s\": %s" +msgstr "\"%s\" veritabanına bağlanılamadı: %s" + +#: pg_dumpall.c:1785 +#, c-format +msgid "could not get server version" +msgstr "sunucu sürüm bilgisi alınamadı" + +#: pg_dumpall.c:1791 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "\"%s\" sürüm bilgisi ayrıştırılamadı" + +#: pg_dumpall.c:1863 pg_dumpall.c:1886 +#, c-format +msgid "executing %s" +msgstr "çalıştırılıyor: %s" + +#: pg_restore.c:314 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "-d/--dbname ve -f/--file seçeneklerinden biri belirtilmeli" + +#: pg_restore.c:323 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "-d/--dbname ve -f/--file seçenekleri birlikte kullanılamaz" + +#: pg_restore.c:349 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "-C/--create ve -1/--single-transaction seçenekleri birlikte kullanılamaz" + +#: pg_restore.c:363 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "azami paralel iş sayısı %d" + +#: pg_restore.c:372 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "hem --single-transaction hem de çoklu iş (multiple jobs) aynı anda belirtilemez" + +#: pg_restore.c:414 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "tanımlanamayan arşiv formatı \"%s\"; lütfen \"c\", \"d\", ya da \"t\" seçeneğini belirtin" + +#: pg_restore.c:454 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "geri yükleme sırasında es geçilen hatalar: %d" + +#: pg_restore.c:467 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s, pg_dump tarafından oluşturulan PostgreSQL arşivinden veritabanı geri yükleniyor.\n" +"\n" + +#: pg_restore.c:469 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [SEÇENEK]... [DOSYA]\n" + +#: pg_restore.c:472 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME bağlanacak veritabanının adı\n" + +#: pg_restore.c:473 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=DOSYA_ADI çıktı dosya adı (stdout için -)\n" + +#: pg_restore.c:474 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t yedek dosya biçimi (otomatik olmalı)\n" + +#: pg_restore.c:475 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list arşivin kısa içeriğini yaz\n" + +#: pg_restore.c:476 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose verbose modu\n" + +#: pg_restore.c:477 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version sürüm bilgisini gösterir ve sonra çıkar\n" + +#: pg_restore.c:478 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help bu yardımı gösterir ve sonra çıkar\n" + +#: pg_restore.c:480 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"Geri güklemeyi kontrol eden seçenekler:\n" + +#: pg_restore.c:481 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only sadece veriyi geri yükle, şemaları değil\n" + +#: pg_restore.c:483 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create hedef veritabanını oluştur\n" + +#: pg_restore.c:484 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error hata durumunda çık, varsayılan seçenek ise devam et\n" + +#: pg_restore.c:485 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=AD adı geçen indeksi geri yükle\n" + +#: pg_restore.c:486 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=SAYI geri yükleme için belirtilen sayı kadar paralel süreç kullan\n" + +#: pg_restore.c:487 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=DOSYAADI çıktıyı seçmek/sıralamak için\n" +" bu dosyadaki içindekiler tablosunu kullan\n" + +#: pg_restore.c:489 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=AD sadece bu şemaya ait nesneleri geri yükle\n" + +#: pg_restore.c:490 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=AD bu şemadaki nesneleri geri yükleme\n" + +#: pg_restore.c:492 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) adı geçen fonksiyonu geri yükle\n" + +#: pg_restore.c:493 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only sadece şemayı geri yükle, veriyi değil\n" + +#: pg_restore.c:494 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=AD tetikleyicileri (trigger) devre dışı bırakmak için kullanılacak superuser kullanıcı adı\n" + +#: pg_restore.c:495 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=AD adı geçen nesneyi (tablo, görünüm, vb.) geri yükle\n" + +#: pg_restore.c:496 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=AD adı geçen tetikleyiciyi geri yükle\n" + +#: pg_restore.c:497 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges erişim haklarının geri yüklemesini atla (grant/revoke)\n" + +#: pg_restore.c:498 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction tek bir transaction olarak geri yükle\n" + +#: pg_restore.c:500 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security satır güvenliğini etkinleştir\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments açıklamaları (comments) yedekleme\n" + +#: pg_restore.c:503 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables oluşturulamayan tabloların verilerini geri\n" +" yükleme\n" + +#: pg_restore.c:505 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications yayınları geri yükleme\n" + +#: pg_restore.c:506 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels güvenlik etiketlerini geri yükleme\n" + +#: pg_restore.c:507 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions abonelikleri geri yükleme\n" + +#: pg_restore.c:508 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces tablespace atamalarını geri yükleme\n" + +#: pg_restore.c:509 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=BÖLÜM belirtilen bölümü yedekle (pre-data, data, veya post-data)\n" + +#: pg_restore.c:522 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROL ADI geri yüklemeden önce SET ROLE işlemini gerçekleştir\n" + +#: pg_restore.c:524 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"-I, -n, -N, -P, -t, -T, ve --section seçenekleri, çoklu nesnelerin seçilmesi için\n" +"birden fazla kez kullanılabilir ve belirtilebilir\n" +"\n" + +#: pg_restore.c:527 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"Eğer giriş dosya adı verilmemişse, standart giriş akımı (stdin) kulanılacaktır.\n" +"\n" + +#~ msgid "reading extended statistics for table \"%s.%s\"\n" +#~ msgstr "\"%s.%s\" tablosunun genişletilmiş istatistikleri okunuyor\n" + +#~ msgid "%s: could not parse ACL list (%s) for database \"%s\"\n" +#~ msgstr "%1$s: \"%3$s\" veritabanı için ACL (%2$s) listesi ayrıştırılamadı\n" + +#~ msgid "Got %d rows instead of one from: %s" +#~ msgstr "%2$s sorgusundan bir yerine %1$d satır alındı" + +#~ msgid "No rows found for enum" +#~ msgstr "Enum için veri bulunamadı" + +#~ msgid "INSERT (-d, -D) and OID (-o) options cannot be used together\n" +#~ msgstr "INSERT (-d, -D) ve OID (-o)seçenekleri beraber kullanılamaz\n" + +#~ msgid "" +#~ " --disable-dollar-quoting\n" +#~ " disable dollar quoting, use SQL standard quoting\n" +#~ msgstr "" +#~ " --disable-dollar-quoting\n" +#~ " dollar quoting kullanmayı engelle, standart SQL quoting kullan\n" + +#~ msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +#~ msgstr " -x, --no-privileges yetkileri aktarmayı engelle (grant/revoke)\n" + +#~ msgid " -s, --schema-only dump only the schema, no data\n" +#~ msgstr " -s, --schema-only sadece şemayı dump et, veriyi etme\n" + +#~ msgid " -o, --oids include OIDs in dump\n" +#~ msgstr " -o, --oids dump içinde OIDleri de içer\n" + +#~ msgid " -D, --column-inserts dump data as INSERT commands with column names\n" +#~ msgstr " -D, --column-inserts veriyi kolon adları ile insert komutu olarak dump et.\n" + +#~ msgid " -d, --inserts dump data as INSERT, rather than COPY, commands\n" +#~ msgstr " -d, --inserts verileri COPYkomutları yerine INSERT olarak dump et\n" + +#~ msgid " -a, --data-only dump only the data, not the schema\n" +#~ msgstr " -a, --data-only sadece veriyi dump eder, şemayı etmez\n" + +#~ msgid "" +#~ " -i, --ignore-version proceed even when server version mismatches\n" +#~ " pg_dumpall version\n" +#~ msgstr "" +#~ " -i, --ignore-version sunucunun sürümü uyuşmadığı durumda\n" +#~ " bile devam et\n" + +#~ msgid "" +#~ " --use-set-session-authorization\n" +#~ " use SESSION AUTHORIZATION commands instead of\n" +#~ " OWNER TO commands\n" +#~ msgstr "" +#~ " --use-set-session-authorization\n" +#~ " OWNER TO komutun yerine\n" +#~ " SESSION AUTHORIZATION komutunu kullan\n" + +#~ msgid " -c, --clean clean (drop) schema prior to create\n" +#~ msgstr " -c, --clean şemayı yaratmadan önce onu temizle (kaldır)\n" + +#~ msgid " -i, --ignore-version proceed even when server version mismatches\n" +#~ msgstr " -i, --ignore-version sunucunun sürümü uyuşmadığında bile devam et\n" + +#~ msgid "%s: no result from server\n" +#~ msgstr "%s: sunucudan sonuç gelmedi\n" + +#~ msgid "aborting because of version mismatch (Use the -i option to proceed anyway.)\n" +#~ msgstr "sürüm uyuşmazlığı yüzünden işlem duruduruldu (Buna rağmen devam etmek için -i seçeneği kullanın).\n" + +#~ msgid "archive format is %d\n" +#~ msgstr "%d arşiv biçimi\n" + +#~ msgid "expected %d triggers on table \"%s\" but found %d\n" +#~ msgstr "\"%2$s\" tablosu zerinde %1$d tetikleyici beklenirken %3$d bulundu\n" + +#~ msgid "" +#~ " -S, --superuser=NAME specify the superuser user name to use in\n" +#~ " plain text format\n" +#~ msgstr "" +#~ " -S, --superuser=NAME düz metin biçiminde kullanılacak superuser\n" +#~ " kullanıcısının adı\n" + +#~ msgid " -c, --clean clean (drop) schema prior to create\n" +#~ msgstr " -c, --clean şemayı oluşturmadan önce onu temizle (kaldır)\n" + +#~ msgid "" +#~ " -i, --ignore-version proceed even when server version mismatches\n" +#~ " pg_dump version\n" +#~ msgstr "" +#~ " -i, --ignore-version sunucunun sürümü ile pg_dump'ın sürümü eşleşmezse\n" +#~ " bile devam et\n" + +#~ msgid "User name: " +#~ msgstr "Kullanıcı adı: " + +#~ msgid "requested %d byte, got %d from lookahead and %d from file\n" +#~ msgid_plural "requested %d bytes, got %d from lookahead and %d from file\n" +#~ msgstr[0] "%d bayt istenildi, lookahead'denn %d, dosyadan ise %d alındı\n" +#~ msgstr[1] "%d bayt istenildi, lookahead'denn %d, dosyadan ise %d alındı\n" + +#~ msgid "read %lu byte into lookahead buffer\n" +#~ msgid_plural "read %lu bytes into lookahead buffer\n" +#~ msgstr[0] "lookahead artalanına %lu bayt okundu\n" +#~ msgstr[1] "lookahead artalanına %lu bayt okundu\n" + +#~ msgid "query returned %d rows instead of one: %s\n" +#~ msgstr "sorgu bir yerine %d satır döndirdi: %s\n" + +#~ msgid "compression support is disabled in this format\n" +#~ msgstr "bu formatta sıkıştırma desteği devre dışı bırakılmıştır\n" + +#~ msgid "dumping a specific TOC data block out of order is not supported without ID on this input stream (fseek required)\n" +#~ msgstr "sıra dışı TOC veri blokun aktarılması, giriş akımında ID olmadan desteklenmemektedir (fseek() gerekir)\n" + +#~ msgid "no label definitions found for enum ID %u\n" +#~ msgstr "%u enum ID'si için etiket tanımları bulunamadı \n" + +#~ msgid "saving large object comments\n" +#~ msgstr "large object açıklamaları kaydediliyor\n" + +#~ msgid "dumpBlobs(): could not open large object: %s" +#~ msgstr "dumpBlobs(): large object açılamadı: %s" + +#~ msgid "cannot reopen non-seekable file\n" +#~ msgstr "aranamayan dosya yeniden açılamadı\n" + +#~ msgid "cannot reopen stdin\n" +#~ msgstr "stdin açılamıyor\n" + +#~ msgid "query returned no rows: %s\n" +#~ msgstr "sorgu hiçbir satır döndürmedi: %s\n" + +#~ msgid "%s: invalid -X option -- %s\n" +#~ msgstr "%s: geçersiz -X seçeneği -- %s\n" + +#~ msgid "could not change directory to \"%s\"" +#~ msgstr "çalışma dizini \"%s\" olarak değiştirilemedi" + +#~ msgid "%s: could not parse version \"%s\"\n" +#~ msgstr "%s: \"%s\" sürüm bilgisi ayrıştırılamadı\n" + +#~ msgid "%s: out of memory\n" +#~ msgstr "%s: yetersiz bellek\n" + +#~ msgid "" +#~ " --use-set-session-authorization\n" +#~ " use SET SESSION AUTHORIZATION commands instead of\n" +#~ " ALTER OWNER commands to set ownership\n" +#~ msgstr "" +#~ " --use-set-session-authorization\n" +#~ " Sahipliği ayarlamak için ALTER OWNER komutunun yerine\n" +#~ " SET SESSION AUTHORIZATION komutunu kullan\n" + +#~ msgid " --disable-triggers disable triggers during data-only restore\n" +#~ msgstr " --disable-triggers sadece veri geri yüklemede tetikleyicileri devre dışı bırak\n" + +#~ msgid " -O, --no-owner skip restoration of object ownership\n" +#~ msgstr " -O, --no-owner nesne sahipliğini ayarlayan komutlarının oluşturmasını engelle\n" + +#~ msgid " -c, --clean clean (drop) database objects before recreating\n" +#~ msgstr " -c, --clean veritabanı nesnelerini yeniden yaratmadan önce onları kaldır (sil)\n" + +#~ msgid " --version output version information, then exit\n" +#~ msgstr " --version sürüm bilgisini gösterir ve çıkar\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help bu yardımı gösterir ve çıkar\n" + +#~ msgid "mismatch in actual vs. predicted file position (%s vs. %s)\n" +#~ msgstr "gerçek ile beklenilen dosya pozisyonunda uyumsuzluk (%s ile %s)\n" + +#~ msgid "could not output padding at end of tar member\n" +#~ msgstr "tar öğesinin arkasına doldurma alanı eklenemedi\n" + +#~ msgid "archive member too large for tar format\n" +#~ msgstr "tar biçimi için arşiv öğesi çok büyük\n" + +#~ msgid "could not write null block at end of tar archive\n" +#~ msgstr "arşivin sonunda null blok yazılamadı\n" + +#~ msgid "restoring large object OID %u\n" +#~ msgstr "large-object %u geri yükleniyor\n" + +#~ msgid "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n" +#~ msgstr "geçersiz COPY komutu -- \"%s\" satırında %lu pozisyonunda \"from stdin\" bulunamadı\n" + +#~ msgid "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n" +#~ msgstr "geçersiz COPY komutu -- \"%s\" satırında \"copy\" bulunamadı\n" + +#~ msgid "could not close large object file\n" +#~ msgstr "large object dosyası kapatılamadı\n" + +#~ msgid "could not open large object TOC for output: %s\n" +#~ msgstr "çıktı için large object TOC açılamadı: %s\n" + +#~ msgid "could not write byte\n" +#~ msgstr "byte yazılamadı\n" + +#~ msgid "could not open large object TOC for input: %s\n" +#~ msgstr "girdi için large object TOC açılamadı: %s\n" + +#~ msgid "could not close data file after reading\n" +#~ msgstr "veri dosyası okunduktan sonra kapatılamadı\n" + +#~ msgid "" +#~ "WARNING:\n" +#~ " This format is for demonstration purposes; it is not intended for\n" +#~ " normal use. Files will be written in the current working directory.\n" +#~ msgstr "" +#~ "UYARI:\n" +#~ " Bu biçim sadece demo amaçlıdır. Normal kullanım için\n" +#~ " denenmemelidir. Dosyalar mecvut çalışma dizinine yazılacaktır.\n" + +#~ msgid "file archiver" +#~ msgstr "dosya arşivleyicisi" + +#~ msgid "could not write byte: %s\n" +#~ msgstr "bayt yazılamadı: %s\n" + +#~ msgid "could not find slot of finished worker\n" +#~ msgstr "bitmiş sürecin yuvasu bulunamadı\n" + +#~ msgid "could not create worker thread: %s\n" +#~ msgstr "işçi threadi yaratılamadı: %s\n" + +#~ msgid "parallel_restore should not return\n" +#~ msgstr "parallel_restore dönmemeli\n" + +#~ msgid "worker process crashed: status %d\n" +#~ msgstr "worker sürecii çöktü: Durum %d\n" + +#~ msgid "could not write to custom output routine\n" +#~ msgstr "kullanıcı tanımlı çıktı yordamına yazma hatası\n" + +#~ msgid "setting owner and privileges for %s %s\n" +#~ msgstr "%s %s için sahiplik ve izinler ayarlanıyor\n" + +#~ msgid "-C and -c are incompatible options\n" +#~ msgstr "-C ve -c seçenekler bir arada kullanılamaz\n" + +#~ msgid "cannot duplicate null pointer\n" +#~ msgstr "null pointer dump edilemez\n" + +#~ msgid "SQL command failed\n" +#~ msgstr "SQL komutu başarısız\n" + +#~ msgid "query to get data of sequence \"%s\" returned name \"%s\"\n" +#~ msgstr "\"%s\" sequence verisini getirecek sorgu \"%s\" adını getirdi\n" + +#~ msgid "found more than one entry for pg_indexes in pg_class\n" +#~ msgstr "pg_class içinde pg_indexes için birden çok kayıt bulundu\n" + +#~ msgid "could not find entry for pg_indexes in pg_class\n" +#~ msgstr "pg_class içinde pg_indexes için kayıt bulunamadı\n" + +#~ msgid "found more than one pg_database entry for this database\n" +#~ msgstr "bu veritabanı için birden fazla pg_database kaydı bulundu\n" + +#~ msgid "missing pg_database entry for this database\n" +#~ msgstr "bu veritabanı için pg_database kaydı bulunamadı\n" + +#~ msgid "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n" +#~ msgstr "dumpDatabase(): pg_largeobject_metadata.relfrozenxid bulunamadı\n" + +#~ msgid "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n" +#~ msgstr "dumpDatabase(): pg_largeobject.relfrozenxid bulunamadı\n" + +#~ msgid "query returned more than one (%d) pg_database entry for database \"%s\"\n" +#~ msgstr "Sorgu, birden fazla (%d) sonucu \"%s\" veritabanının pg_database kaydı için döndürdü\n" + +#~ msgid "missing pg_database entry for database \"%s\"\n" +#~ msgstr "\"%s\" veritabanı için pg_database kaydı bulunamadı\n" + +#~ msgid "server version must be at least 7.3 to use schema selection switches\n" +#~ msgstr "şema seçim anahtarlarını kullanmak için sunucu sürümü 7.3 ya da daha yüksek olmalıdır\n" + +#~ msgid "*** aborted because of error\n" +#~ msgstr "*** hata nedeniyle durduruldu\n" + +#~ msgid " --version output version information, then exit\n" +#~ msgstr " --version sürüm bilgisini ver ve çık\n" + +#~ msgid " --help show this help, then exit\n" +#~ msgstr " --help bu yardımı göster ve sonra çık\n" + +#~ msgid "could not parse version string \"%s\"\n" +#~ msgstr "\"%s\" sürüm bilgisi ayrıştırılamadı\n" + +#~ msgid "could not open output file \"%s\" for writing\n" +#~ msgstr "\"%s\" çıktı dosyası yazmak için açılamadı\n" + +#~ msgid "%s: invalid number of parallel jobs\n" +#~ msgstr "%s: parallel iş sayısı geçersiz\n" + +#~ msgid "%s: options -c/--clean and -a/--data-only cannot be used together\n" +#~ msgstr "%s: -c/--clean ve -a/--data-only seçenekleri aynı anda kullanılamaz\n" + +#~ msgid "%s: options -s/--schema-only and -a/--data-only cannot be used together\n" +#~ msgstr "%s: -s/--schema-only ve -a/--data-only seçenekleri aynı anda kullanılamaz\n" + +#~ msgid "%s: query was: %s\n" +#~ msgstr "%s: sorgu şu idi: %s\n" + +#~ msgid "%s: query failed: %s" +#~ msgstr "%s: sorgu başarısız oldu: %s" + +#~ msgid "%s: executing %s\n" +#~ msgstr "%s: %s yürütülüyor\n" + +#~ msgid "%s: invalid client encoding \"%s\" specified\n" +#~ msgstr "%s: belirtilen \"%s\" istemci dil kodlaması geçersiz\n" + +#~ msgid "%s: option --if-exists requires option -c/--clean\n" +#~ msgstr "%s: --if-exists seçeneği -c/--clean seçeneğini gerektirir\n" + +#~ msgid "sorter" +#~ msgstr "sorter" + +#~ msgid "WARNING: could not parse reloptions array\n" +#~ msgstr "UYARI: reloptions dizisi ayrıştırılamadı\n" + +#~ msgid "schema with OID %u does not exist\n" +#~ msgstr "OID %u olan şema mevcut değil\n" + +#~ msgid "(The INSERT command cannot set OIDs.)\n" +#~ msgstr "(INSERT komutu OIDleri ayarlayamaz.)\n" + +#~ msgid "options --inserts/--column-inserts and -o/--oids cannot be used together\n" +#~ msgstr "--inserts/--column-inserts ve -o/--oids beraber kullanılamazlar\n" + +#~ msgid "TOC Entry %s at %s (length %s, checksum %d)\n" +#~ msgstr "%2$s adresinde %1$s TOC Girişi (uzunluk %3$s, checksum %4$d)\n" + +#~ msgid "skipping tar member %s\n" +#~ msgstr "%s tar öğesi atlandı\n" + +#~ msgid "now at file position %s\n" +#~ msgstr "şu an dosyanın %s yerinde\n" + +#~ msgid "moving from position %s to next member at file position %s\n" +#~ msgstr "dosya içerisinde %s yerinden bir sonraki %s yerine geçiş yapılamıyor\n" + +#~ msgid "tar archiver" +#~ msgstr "tar archiver" + +#~ msgid "could not create directory \"%s\": %s\n" +#~ msgstr "\"%s\" dizini oluşturulamadı: %s\n" + +#~ msgid "could not read directory \"%s\": %s\n" +#~ msgstr "\"%s\" dizini okunamıyor: %s\n" + +#~ msgid "directory archiver" +#~ msgstr "directory archiver" + +#~ msgid "COPY failed for table \"%s\": %s" +#~ msgstr "COPY \"%s\" tablosu için başarısız oldu: %s" + +#~ msgid "%s: %s Command was: %s\n" +#~ msgstr "" +#~ "%s: %s Komut şuydu: %s\n" +#~ "\n" + +#~ msgid "archiver (db)" +#~ msgstr "archiver (db)" + +#~ msgid "custom archiver" +#~ msgstr "custom archiver" + +#~ msgid "reducing dependencies for %d\n" +#~ msgstr "%d için bağımlılıklar azaltılıyor\n" + +#~ msgid "transferring dependency %d -> %d to %d\n" +#~ msgstr "%d -> %d bağımlılığı %d olarak aktarılıyor\n" + +#~ msgid "no item ready\n" +#~ msgstr "hiç bir öğe hazır değil\n" + +#~ msgid "entering restore_toc_entries_postfork\n" +#~ msgstr "restore_toc_entries_postfork'a giriliyor\n" + +#~ msgid "entering restore_toc_entries_parallel\n" +#~ msgstr "restore_toc_entries_parallel'e giriliyor\n" + +#~ msgid "entering restore_toc_entries_prefork\n" +#~ msgstr "restore_toc_entries_prefork'a giriliyor\n" + +#~ msgid "could not set default_tablespace to %s: %s" +#~ msgstr "default_tablespace %s olarak değiştirilemedi: %s" + +#~ msgid "could not set search_path to \"%s\": %s" +#~ msgstr "search_path \"%s\" olarak değiştirilemedi: %s" + +#~ msgid "could not set default_with_oids: %s" +#~ msgstr "default_with_oids ayarlanamıyor: %s" + +#~ msgid "read TOC entry %d (ID %d) for %s %s\n" +#~ msgstr "%3$s %4$s için TOC öğe %1$d (ID %2$d) okunuyor\n" + +#~ msgid "allocating AH for %s, format %d\n" +#~ msgstr "%s için AH ayırılıyor, biçim %d\n" + +#~ msgid "attempting to ascertain archive format\n" +#~ msgstr "arşiv formatı doğrulanmaya çalışılıyor\n" + +#~ msgid "-C and -1 are incompatible options\n" +#~ msgstr "-C ve -1 uyumsuz seçeneklerdir\n" + +#~ msgid "archiver" +#~ msgstr "archiver" + +#~ msgid "parallel archiver" +#~ msgstr "paralel arşivleyici" + +#~ msgid "compress_io" +#~ msgstr "compress_io" + +#~ msgid "child process was terminated by signal %s" +#~ msgstr "alt süreç %s sinyali tarafından sonlandırılmıştır" + +#~ msgid "could not read symbolic link \"%s\"" +#~ msgstr "symbolic link \"%s\" okuma hatası" + +#~ msgid "could not change directory to \"%s\": %s" +#~ msgstr "çalışma dizini \"%s\" olarak değiştirilemedi: %s" diff --git a/src/bin/pg_dump/po/uk.po b/src/bin/pg_dump/po/uk.po new file mode 100644 index 0000000..4873c66 --- /dev/null +++ b/src/bin/pg_dump/po/uk.po @@ -0,0 +1,2665 @@ +msgid "" +msgstr "" +"Project-Id-Version: postgresql\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2022-05-17 15:33+0000\n" +"PO-Revision-Date: 2022-06-19 10:10\n" +"Last-Translator: \n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n" +"X-Crowdin-Project: postgresql\n" +"X-Crowdin-Project-ID: 324573\n" +"X-Crowdin-Language: uk\n" +"X-Crowdin-File: /REL_14_STABLE/pg_dump.pot\n" +"X-Crowdin-File-ID: 772\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "збій: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "помилка: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "попередження: " + +#: ../../common/exec.c:141 ../../common/exec.c:258 ../../common/exec.c:304 +#, c-format +msgid "could not identify current directory: %m" +msgstr "не вдалося визначити поточний каталог: %m" + +#: ../../common/exec.c:160 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "невірний бінарний файл \"%s\"" + +#: ../../common/exec.c:210 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "неможливо прочитати бінарний файл \"%s\"" + +#: ../../common/exec.c:218 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "неможливо знайти \"%s\" для виконання" + +#: ../../common/exec.c:274 ../../common/exec.c:313 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "не вдалося змінити каталог на \"%s\": %m" + +#: ../../common/exec.c:291 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "не можливо прочитати символічне послання \"%s\": %m" + +#: ../../common/exec.c:414 parallel.c:1614 +#, c-format +msgid "%s() failed: %m" +msgstr "%s() помилка: %m" + +#: ../../common/exec.c:527 ../../common/exec.c:572 ../../common/exec.c:664 +msgid "out of memory" +msgstr "недостатньо пам'яті" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "неможливо виконати команду" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "команду не знайдено" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "дочірній процес завершився з кодом виходу %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "дочірній процес перервано через помилку 0х%X" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "дочірній процес перервано через сигнал %d: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "дочірній процес завершився з невизнаним статусом %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "читання розширень" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "ідентифікація членів розширення" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "читання схемів" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "читання користувацьких таблиць" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "читання користувацьких функцій" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "читання користувацьких типів" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "читання процедурних мов" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "читання користувацьких агрегатних функцій" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "читання користувацьких операторів" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "читання користувацьких методів доступу" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "читання користувацьких класів операторів" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "читання користувацьких сімейств операторів" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "читання користувацьких парсерів текстового пошуку" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "читання користувацьких шаблонів текстового пошуку" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "читання користувацьких словників текстового пошуку" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "читання користувацьких конфігурацій текстового пошуку" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "читання користувацьких джерел сторонніх даних" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "читання користувацьких сторонніх серверів" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "читання прав за замовчуванням" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "читання користувацьких сортувань" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "читання користувацьких перетворень" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "читання типу приведення" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "читання перетворень" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "читання інформації про успадкування таблиці" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "читання тригерів подій" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "пошук таблиць розширень" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "пошук відносин успадкування" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "читання інформації про стовпці цікавлячої таблиці" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "помітка успадкованих стовпців в підтаблицях" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "читання індексів" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "помітка індексів в секційних таблицях" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "читання розширеної статистики" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "читання обмежень" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "читання тригерів" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "читання правил перезаписування" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "читання політик" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "читання публікацій" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "читання публікацій учасників" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "читання підписок" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "неприпустиме число батьківських елементів %d для таблиці \"%s\"" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "помилка перевірки, батьківський елемент ідентифікатора OID %u для таблиці \"%s\" (ідентифікатор OID %u) не знайдено" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "не вдалося проаналізувати числовий масив \"%s\": забагато чисел" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "не вдалося проаналізувати числовий масив \"%s\": неприпустимий характер числа" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "невірний код стиснення: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "зібрано без підтримки zlib" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "не вдалося ініціалізувати бібліотеку стиснення: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "не вдалося закрити потік стиснення: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "не вдалося стиснути дані: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "не вдалося розпакувати дані: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "не вдалося закрити бібліотеку стиснення: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:554 pg_backup_tar.c:557 +#, c-format +msgid "could not read from input file: %s" +msgstr "не вдалося прочитати з вхідного файлу: %s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:553 +#: pg_backup_tar.c:790 pg_backup_tar.c:813 +#, c-format +msgid "could not read from input file: end of file" +msgstr "не вдалося прочитати з вхідного файлу: кінець файлу" + +#: parallel.c:254 +#, c-format +msgid "%s() failed: error code %d" +msgstr "%s() помилка: код помилки %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "не вдалося створити канали зв'язку: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "не вдалося створити робочий процес: %m" + +#: parallel.c:1151 +#, c-format +msgid "unrecognized command received from leader: \"%s\"" +msgstr "нерозпізнана команда отримана від лідера: \"%s\"" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "отримане невірне повідомлення від робочого процесу: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "не вдалося отримати блокування відношення \"%s\"\n" +"Це, зазвичай, означає, що хтось зробив запит на монопольне блокування таблиці після того, як батьківський процес pg_dump отримав початкове блокування спільного доступу для таблиці." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "робочий процес завершився несподівано" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "не вдалося записати до каналу зв'язку: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: не вдалося створити сокет: код помилки %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: не вдалося прив'язати: код помилки %d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: не вдалося прослухати: код помилки %d" + +#: parallel.c:1764 +#, c-format +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s() помилка: код помилки %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: не вдалося створити другий сокет: код помилки %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: не вдалося зв'язатися з сокетом: код помилки %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: не вдалося прийняти зв'язок: код помилки %d" + +#: pg_backup_archiver.c:278 pg_backup_archiver.c:1578 +#, c-format +msgid "could not close output file: %m" +msgstr "не вдалося закрити вихідний файл: %m" + +#: pg_backup_archiver.c:322 pg_backup_archiver.c:326 +#, c-format +msgid "archive items not in correct section order" +msgstr "елементи архіву в неправильному порядку" + +#: pg_backup_archiver.c:332 +#, c-format +msgid "unexpected section code %d" +msgstr "неочікуваний код розділу %d" + +#: pg_backup_archiver.c:369 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "паралельне відновлення не підтримується з цим файлом архівного формату" + +#: pg_backup_archiver.c:373 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "паралельне відновлення не підтримується з архівами, зробленими pre-8.0 pg_dump" + +#: pg_backup_archiver.c:391 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "не вдалося відновити зі стиснутого архіву (встановлена версія не підтримує стискання)" + +#: pg_backup_archiver.c:408 +#, c-format +msgid "connecting to database for restore" +msgstr "підключення до бази даних для відновлення" + +#: pg_backup_archiver.c:410 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "прямі з'днання з базою даних не підтримуються в архівах у версіях до 1.3" + +#: pg_backup_archiver.c:453 +#, c-format +msgid "implied data-only restore" +msgstr "мається на увазі відновлення лише даних" + +#: pg_backup_archiver.c:519 +#, c-format +msgid "dropping %s %s" +msgstr "видалення %s %s" + +#: pg_backup_archiver.c:614 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "не вдалося знайти, куди вставити IF EXISTS в інструкції \"%s\"" + +#: pg_backup_archiver.c:770 pg_backup_archiver.c:772 +#, c-format +msgid "warning from original dump file: %s" +msgstr "попередження з оригінального файлу дамп: %s" + +#: pg_backup_archiver.c:787 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "створення %s \"%s.%s\"" + +#: pg_backup_archiver.c:790 +#, c-format +msgid "creating %s \"%s\"" +msgstr "створення %s \" \"%s\"" + +#: pg_backup_archiver.c:840 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "підключення до нової бази даних \"%s\"" + +#: pg_backup_archiver.c:867 +#, c-format +msgid "processing %s" +msgstr "обробка %s" + +#: pg_backup_archiver.c:887 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "обробка даних для таблиці \"%s.%s\"" + +#: pg_backup_archiver.c:949 +#, c-format +msgid "executing %s %s" +msgstr "виконання %s %s" + +#: pg_backup_archiver.c:988 +#, c-format +msgid "disabling triggers for %s" +msgstr "вимкнення тригерів для %s" + +#: pg_backup_archiver.c:1014 +#, c-format +msgid "enabling triggers for %s" +msgstr "увімкнення тригерів для %s" + +#: pg_backup_archiver.c:1042 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "внутрішня помилка - WriteData не може бути викликана поза контекстом підпрограми DataDumper " + +#: pg_backup_archiver.c:1225 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "вивід великих об'єктів не підтримується у вибраному форматі" + +#: pg_backup_archiver.c:1283 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "відновлено %d великий об'єкт" +msgstr[1] "відновлено %d великих об'єкти" +msgstr[2] "відновлено %d великих об'єктів" +msgstr[3] "відновлено %d великих об'єктів" + +#: pg_backup_archiver.c:1304 pg_backup_tar.c:733 +#, c-format +msgid "restoring large object with OID %u" +msgstr "відновлення великого об'єкту з OID %u" + +#: pg_backup_archiver.c:1316 +#, c-format +msgid "could not create large object %u: %s" +msgstr "не вдалося створити великий об'єкт %u: %s" + +#: pg_backup_archiver.c:1321 pg_dump.c:3729 +#, c-format +msgid "could not open large object %u: %s" +msgstr "не вдалося відкрити великий об'єкт %u: %s" + +#: pg_backup_archiver.c:1377 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "не вдалося відкрити файл TOC \"%s\": %m" + +#: pg_backup_archiver.c:1405 +#, c-format +msgid "line ignored: %s" +msgstr "рядок проігноровано: %s" + +#: pg_backup_archiver.c:1412 +#, c-format +msgid "could not find entry for ID %d" +msgstr "не вдалося знайти введення для ID %d" + +#: pg_backup_archiver.c:1435 pg_backup_directory.c:222 +#: pg_backup_directory.c:599 +#, c-format +msgid "could not close TOC file: %m" +msgstr "не вдалося закрити файл TOC: %m" + +#: pg_backup_archiver.c:1549 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:586 pg_backup_directory.c:649 +#: pg_backup_directory.c:668 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "не вдалося відкрити вихідний файл \"%s\": %m" + +#: pg_backup_archiver.c:1551 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "не вдалося відкрити вихідний файл: %m" + +#: pg_backup_archiver.c:1645 +#, c-format +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "записано %zu байт даних великого об'єкта (результат = %d)" +msgstr[1] "записано %zu байти даних великого об'єкта (результат = %d)" +msgstr[2] "записано %zu байтів даних великого об'єкта (результат = %d)" +msgstr[3] "записано %zu байтів даних великого об'єкта (результат = %d)" + +#: pg_backup_archiver.c:1651 +#, c-format +msgid "could not write to large object: %s" +msgstr "не вдалося записати до великого об'єкту: %s" + +#: pg_backup_archiver.c:1741 +#, c-format +msgid "while INITIALIZING:" +msgstr "при ІНІЦІАЛІЗАЦІЇ:" + +#: pg_backup_archiver.c:1746 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "при ОБРОБЦІ TOC:" + +#: pg_backup_archiver.c:1751 +#, c-format +msgid "while FINALIZING:" +msgstr "при ЗАВЕРШЕННІ:" + +#: pg_backup_archiver.c:1756 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "зі входження до TOC %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1832 +#, c-format +msgid "bad dumpId" +msgstr "невірний dumpId" + +#: pg_backup_archiver.c:1853 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "невірна таблиця dumpId для елементу даних таблиці" + +#: pg_backup_archiver.c:1945 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "неочікувана позначка зсуву даних %d" + +#: pg_backup_archiver.c:1958 +#, c-format +msgid "file offset in dump file is too large" +msgstr "зсув файлу у файлі дампу завеликий" + +#: pg_backup_archiver.c:2096 pg_backup_archiver.c:2106 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "ім'я каталогу задовге: \"%s\"" + +#: pg_backup_archiver.c:2114 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "каталог \"%s\" не схожий на архівний (\"toc.dat\" не існує)" + +#: pg_backup_archiver.c:2122 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:395 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "не вдалося відкрити вхідний файл \"%s\": %m" + +#: pg_backup_archiver.c:2129 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "не вдалося відкрити вхідний файл: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "could not read input file: %m" +msgstr "не вдалося прочитати вхідний файл: %m" + +#: pg_backup_archiver.c:2137 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "вхідний файл закороткий (прочитано %lu, очікувалось 5)" + +#: pg_backup_archiver.c:2169 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "вхідний файл схожий на дамп текстового формату. Будь ласка, використайте psql." + +#: pg_backup_archiver.c:2175 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "вхідний файл не схожий на архівний (закороткий?)" + +#: pg_backup_archiver.c:2181 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "вхідний файл не схожий на архівний" + +#: pg_backup_archiver.c:2190 +#, c-format +msgid "could not close input file: %m" +msgstr "не вдалося закрити вхідний файл: %m" + +#: pg_backup_archiver.c:2307 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "нерозпізнаний формат файлу \"%d\"" + +#: pg_backup_archiver.c:2389 pg_backup_archiver.c:4413 +#, c-format +msgid "finished item %d %s %s" +msgstr "завершений об'єкт %d %s %s" + +#: pg_backup_archiver.c:2393 pg_backup_archiver.c:4426 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "помилка при робочому процесі: код виходу %d" + +#: pg_backup_archiver.c:2513 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "введення ідентифікатора %d поза діапазоном -- можливо, зміст пошкоджений" + +#: pg_backup_archiver.c:2580 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "відновлення таблиць WITH OIDS більше не підтримується" + +#: pg_backup_archiver.c:2662 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "нерозпізнане кодування \"%s\"" + +#: pg_backup_archiver.c:2667 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "невірний об'єкт КОДУВАННЯ: %s" + +#: pg_backup_archiver.c:2685 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "невірний об'єкт STDSTRINGS: %s" + +#: pg_backup_archiver.c:2710 +#, c-format +msgid "schema \"%s\" not found" +msgstr "схему \"%s\" не знайдено" + +#: pg_backup_archiver.c:2717 +#, c-format +msgid "table \"%s\" not found" +msgstr "таблицю \"%s\" не знайдено" + +#: pg_backup_archiver.c:2724 +#, c-format +msgid "index \"%s\" not found" +msgstr "індекс \"%s\" не знайдено" + +#: pg_backup_archiver.c:2731 +#, c-format +msgid "function \"%s\" not found" +msgstr "функцію \"%s\" не знайдено" + +#: pg_backup_archiver.c:2738 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "тригер \"%s\" не знайдено" + +#: pg_backup_archiver.c:3130 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "не вдалося встановити користувача сеансу для \"%s\": %s" + +#: pg_backup_archiver.c:3262 +#, c-format +msgid "could not set search_path to \"%s\": %s" +msgstr "не вдалося встановити search_path для \"%s\": %s" + +#: pg_backup_archiver.c:3324 +#, c-format +msgid "could not set default_tablespace to %s: %s" +msgstr "не вдалося встановити default_tablespace для %s: %s" + +#: pg_backup_archiver.c:3369 +#, c-format +msgid "could not set default_table_access_method: %s" +msgstr "не вдалося встановити default_table_access_method для : %s" + +#: pg_backup_archiver.c:3461 pg_backup_archiver.c:3619 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "невідомо, як встановити власника об'єкту типу \"%s\"" + +#: pg_backup_archiver.c:3722 +#, c-format +msgid "did not find magic string in file header" +msgstr "в заголовку файлу не знайдено магічного рядка" + +#: pg_backup_archiver.c:3736 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "в заголовку непідтримувана версія (%d.%d)" + +#: pg_backup_archiver.c:3741 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "перевірка на розмір цілого числа (%lu) не вдалася" + +#: pg_backup_archiver.c:3745 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "архів зроблено на архітектурі з більшими цілими числами, деякі операції можуть не виконуватися" + +#: pg_backup_archiver.c:3755 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "очікуваний формат (%d) відрізняється від знайденого формату у файлі (%d)" + +#: pg_backup_archiver.c:3770 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "архів стиснено, але ця інсталяція не підтримує стискання -- дані не будуть доступними " + +#: pg_backup_archiver.c:3804 +#, c-format +msgid "invalid creation date in header" +msgstr "неприпустима дата створення у заголовку" + +#: pg_backup_archiver.c:3938 +#, c-format +msgid "processing item %d %s %s" +msgstr "обробка елементу %d %s %s" + +#: pg_backup_archiver.c:4017 +#, c-format +msgid "entering main parallel loop" +msgstr "введення головного паралельного циклу" + +#: pg_backup_archiver.c:4028 +#, c-format +msgid "skipping item %d %s %s" +msgstr "пропускається елемент %d %s %s " + +#: pg_backup_archiver.c:4037 +#, c-format +msgid "launching item %d %s %s" +msgstr "запуск елементу %d %s %s " + +#: pg_backup_archiver.c:4091 +#, c-format +msgid "finished main parallel loop" +msgstr "головний паралельний цикл завершився" + +#: pg_backup_archiver.c:4127 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "обробка втраченого елементу %d %s %s" + +#: pg_backup_archiver.c:4732 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "не вдалося створити таблицю \"%s\", дані не будуть відновлені" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "неприпустимий ідентифікатор OID для великого об’єкту" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1083 pg_backup_tar.c:1088 +#, c-format +msgid "error during file seek: %m" +msgstr "помилка під час пошуку файлу oobe. xml: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "блок даних %d має неправильну позицію пошуку" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "нерозпізнаний тип блоку даних (%d) під час пошуку архіву" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "не вдалося зайти в архіві блок з ідентифікатором %d -- можливо, через непослідовність запиту відновлення, який не можна обробити через файл, що не допускає довільний вхід" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "не вдалося знайти в архіві блок з ідентифікатором %d -- можливо, архів пошкоджений" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "знайдено неочікуваний блок з ідентифікатором (%d) під час читання даних -- очікувалося %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "нерозпізнаний тип блоку даних %d при відновленні архіву" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "не вдалося прочитати з вхідного файлу: %m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1086 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "не вдалося визначити позицію пошуку у файлі архіву: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "не вдалося закрити архівний файл: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "можливо повторно відкрити лише вхідні архіви" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "паралельне відновлення зі стандартного вводу не підтримується" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "паралельне відновлення з файлу без вільного доступу не підтримується" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "не вдалося набрати позицію пошуку у файлі архіву: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "ущільнювач активний" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "не вдалося отримати версію серверу з libpq" + +#: pg_backup_db.c:53 pg_dumpall.c:1837 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "версія серверу: %s; версія %s: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1839 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "переривання через невідповідність версії серверу" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "вже під'єднано до бази даних" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1666 pg_dumpall.c:1777 +msgid "Password: " +msgstr "Пароль: " + +#: pg_backup_db.c:174 +#, c-format +msgid "could not connect to database" +msgstr "не вдалося зв'язатися з базою даних" + +#: pg_backup_db.c:191 +#, c-format +msgid "reconnection failed: %s" +msgstr "помилка повторного підключення: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1697 pg_dumpall.c:1787 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1900 pg_dumpall.c:1923 +#, c-format +msgid "query failed: %s" +msgstr "запит не вдався: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1901 pg_dumpall.c:1924 +#, c-format +msgid "query was: %s" +msgstr "запит був: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "запит повернув %d рядок замість одного: %s" +msgstr[1] "запит повернув %d рядки замість одного: %s" +msgstr[2] "запит повернув %d рядків замість одного: %s" +msgstr[3] "запит повернув %d рядків замість одного: %s" + +#: pg_backup_db.c:355 +#, c-format +msgid "%s: %sCommand was: %s" +msgstr "%s:%sКоманда була: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "не вдалося виконати запит" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "помилка повернулася від PQputCopyData: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "помилка повернулася від PQputCopyEnd: %s" + +#: pg_backup_db.c:519 +#, c-format +msgid "COPY failed for table \"%s\": %s" +msgstr "КОПІЮВАННЯ для таблиці \"%s\" не вдалося: %s" + +#: pg_backup_db.c:525 pg_dump.c:2130 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "неочікувані зайві результати під час копіювання таблиці \"%s\"" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "не вдалося почати транзакцію бази даних" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "не вдалося затвердити транзакцію бази даних" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "вихідний каталог не вказано" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "не вдалося закрити каталог \"%s\": %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не вдалося створити каталог \"%s\": %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:497 +#: pg_backup_directory.c:533 +#, c-format +msgid "could not write to output file: %s" +msgstr "не можливо записати у вихідний файл: %s" + +#: pg_backup_directory.c:373 +#, c-format +msgid "could not close data file: %m" +msgstr "не вдалося закрити файл даних: %m" + +#: pg_backup_directory.c:407 +#, c-format +msgid "could not close data file \"%s\": %m" +msgstr "не вдалося закрити файл даних \"%s\": %m" + +#: pg_backup_directory.c:447 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "не вдалося відкрити великий об'єкт файлу TOC \"%s\" для вводу: %m" + +#: pg_backup_directory.c:458 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "невірна лінія у великому об'єкті файлу TOC \"%s\": \"%s\"" + +#: pg_backup_directory.c:467 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "помилка читання великого об'єкту файлу TOC \"%s\"" + +#: pg_backup_directory.c:471 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "не вдалося закрити великий об'єкт файлу TOC \"%s\" %m" + +#: pg_backup_directory.c:685 +#, c-format +msgid "could not close blob data file: %m" +msgstr "не вдалося закрити файл бінарних даних: %m" + +#: pg_backup_directory.c:691 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "не вдалося записати зміст у файл oobe. xml" + +#: pg_backup_directory.c:705 +#, c-format +msgid "could not close blobs TOC file: %m" +msgstr "не вдалося закрити файл TOC бінарних даних: %m" + +#: pg_backup_directory.c:724 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "ім'я файлу задовге: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "цей формат не може бути прочитаним" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "не вдалося відкрити файл TOC \"%s\" для виводу: %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "не вдалося відкрити файл TOC для виводу: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "стиснення не підтримується форматом архіватора tar" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "не вдалося відкрити файл TOC \"%s\" для вводу: %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "не вдалося відкрити файл TOC для вводу: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "не вдалося знайти файл \"%s\" в архіві" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "не вдалося згенерувати тимчасове ім'я файлу: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "неможливо відкрити тимчасовий файл" + +#: pg_backup_tar.c:444 +#, c-format +msgid "could not close tar member: %m" +msgstr "не вдалося закрити tar елемент: %m" + +#: pg_backup_tar.c:688 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "неочікуваний синтаксис інструкції копіювання: \"%s\"" + +#: pg_backup_tar.c:955 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "неприпустимий ідентифікатор OID для великих об’єктів (%u)" + +#: pg_backup_tar.c:1102 +#, c-format +msgid "could not close temporary file: %m" +msgstr "не вдалося закрити тимчасовий файл oobe. xml: %m" + +#: pg_backup_tar.c:1111 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "фактична довжина файлу (%s) не відповідає очікуваному (%s)" + +#: pg_backup_tar.c:1168 pg_backup_tar.c:1199 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "не вдалося знайти верхній колонтитул для файлу oobe. xml \"%s\" в архіві tar" + +#: pg_backup_tar.c:1186 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "відновлення даних поза замовленням не підтримується у цьому форматі архіву: вимагаєтсья \"%s\", але перед цим іде \"%s\" у файлі архіву." + +#: pg_backup_tar.c:1233 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "знайдено незавершений tar-заголовок (%lu байт)" +msgstr[1] "знайдено незавершений tar-заголовок (%lu байт)" +msgstr[2] "знайдено незавершений tar-заголовок (%lu байт)" +msgstr[3] "знайдено незавершений tar-заголовок (%lu байт)" + +#: pg_backup_tar.c:1284 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "знайдено пошкоджений tar-верхній колонтитул у %s(очікувалося %d, обчислюється %d) позиція файлу oobe. xml %s" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "нерозпізнане ім’я розділу: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:625 pg_dump.c:642 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "Спробуйте \"%s --help\" для додаткової інформації.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "перевищено межу on_exit_nicely слотів" + +#: pg_dump.c:551 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "рівень стискання має бути у діапазоні 0..9" + +#: pg_dump.c:589 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits повинні бути у діапазоні -15..3" + +#: pg_dump.c:612 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "рядків-на-вставку має бути у діапазоні %d..%d" + +#: pg_dump.c:640 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "забагато аргументів у командному рядку (перший \"%s\")" + +#: pg_dump.c:661 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "параметри -s/--schema-only і -a/--data-only не можуть використовуватись разом" + +#: pg_dump.c:666 +#, c-format +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "параметри -s/--schema-only і --include-foreign-data не можуть використовуватись разом" + +#: pg_dump.c:669 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "параметр --include-foreign-data не підтримується з паралельним резервним копіюванням" + +#: pg_dump.c:673 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "параметри -c/--clean і -a/--data-only не можна використовувати разом" + +#: pg_dump.c:678 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "параметр --if-exists потребує параметр -c/--clean" + +#: pg_dump.c:685 +#, c-format +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "параметр --on-conflict-do-nothing вимагає опції --inserts, --rows-per-insert або --column-inserts" + +#: pg_dump.c:707 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "затребуване стискання недоступне на цій системі -- архів не буде стискатися" + +#: pg_dump.c:728 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "неприпустима кількість паралельних завдань" + +#: pg_dump.c:732 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "паралельне резервне копіювання підтримується лише з форматом \"каталог\"" + +#: pg_dump.c:787 +#, c-format +msgid "Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "У цій версії серверу синхронізовані знімки не підтримуються.\n" +"Якщо вам не потрібні синхронізовані знімки, виконайте \n" +" --no-synchronized-snapshots." + +#: pg_dump.c:793 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "Експортовані знімки не підтримуються цією версією серверу." + +#: pg_dump.c:805 +#, c-format +msgid "last built-in OID is %u" +msgstr "останній вбудований OID %u" + +#: pg_dump.c:814 +#, c-format +msgid "no matching schemas were found" +msgstr "відповідних схем не знайдено" + +#: pg_dump.c:828 +#, c-format +msgid "no matching tables were found" +msgstr "відповідних таблиць не знайдено" + +#: pg_dump.c:850 +#, c-format +msgid "no matching extensions were found" +msgstr "не знайдено відповідних розширень" + +#: pg_dump.c:1020 +#, c-format +msgid "%s dumps a database as a text file or to other formats.\n\n" +msgstr "%s зберігає резервну копію бази даних в текстовому файлі або в інших форматах.\n\n" + +#: pg_dump.c:1021 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "Використання:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [OPTION]... [DBNAME]\n" + +#: pg_dump.c:1024 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "\n" +"General options:\n" +msgstr "\n" +"Основні налаштування:\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=FILENAME ім'я файлу виводу або каталогу\n" + +#: pg_dump.c:1026 +#, c-format +msgid " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr " -F, --format=c|d|t|p формат файлу виводу (спеціальний, каталог, tar,\n" +" звичайний текст (за замовчуванням))\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM використовувати ці паралельні завдання для вивантаження\n" + +#: pg_dump.c:1029 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose детальний режим\n" + +#: pg_dump.c:1030 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію, потім вийти\n" + +#: pg_dump.c:1031 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 рівень стискання для стиснутих форматів\n" + +#: pg_dump.c:1032 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT помилка після очікування TIMEOUT для блокування таблиці\n" + +#: pg_dump.c:1033 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync не чекати безпечного збереження змін на диск\n" + +#: pg_dump.c:1034 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку, потім вийти\n" + +#: pg_dump.c:1036 pg_dumpall.c:631 +#, c-format +msgid "\n" +"Options controlling the output content:\n" +msgstr "\n" +"Параметри, що керують вихідним вмістом:\n" + +#: pg_dump.c:1037 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only вивантажити лише дані, без схеми\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs включити у вивантаження великі об'єкти\n" + +#: pg_dump.c:1039 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs виключити з вивантаження великі об'єкти\n" + +#: pg_dump.c:1040 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean видалити об'єкти бази даних перед перед повторним створенням\n" + +#: pg_dump.c:1041 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create включити у вивантаження команди для створення бази даних\n" + +#: pg_dump.c:1042 +#, c-format +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=PATTERN вивантажити лише вказане(і) розширення\n" + +#: pg_dump.c:1043 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=ENCODING вивантажити дані в кодуванні ENCODING\n" + +#: pg_dump.c:1044 +#, c-format +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATTERN вивантажити лише вказану схему(и)\n" + +#: pg_dump.c:1045 +#, c-format +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN НЕ вивантажувати вказану схему(и)\n" + +#: pg_dump.c:1046 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr " -O, --no-owner пропускати відновлення володіння об'єктами\n" +" при використанні текстового формату\n" + +#: pg_dump.c:1048 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only вивантажити лише схему, без даних\n" + +#: pg_dump.c:1049 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME ім'я користувача, яке буде використовуватись у звичайних текстових форматах\n" + +#: pg_dump.c:1050 +#, c-format +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATTERN вивантажити лише вказані таблиці\n" + +#: pg_dump.c:1051 +#, c-format +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATTERN НЕ вивантажувати вказані таблиці\n" + +#: pg_dump.c:1052 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges не вивантажувати права (надання/відкликання)\n" + +#: pg_dump.c:1053 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade для використання лише утилітами оновлення\n" + +#: pg_dump.c:1054 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts вивантажити дані у вигляді команд INSERT з іменами стовпців\n" + +#: pg_dump.c:1055 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr " --disable-dollar-quoting вимкнути цінову пропозицію $, використовувати SQL стандартну цінову пропозицію\n" + +#: pg_dump.c:1056 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers вимкнути тригери лише під час відновлення даних\n" + +#: pg_dump.c:1057 +#, c-format +msgid " --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr " --enable-row-security активувати захист на рівні рядків (вивантажити лише той вміст, до якого\n" +" користувач має доступ)\n" + +#: pg_dump.c:1059 +#, c-format +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATTERN НЕ вивантажувати дані вказаних таблиць\n" + +#: pg_dump.c:1060 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM змінити параметр за замовчуванням для extra_float_digits\n" + +#: pg_dump.c:1061 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists використовувати IF EXISTS під час видалення об'єктів\n" + +#: pg_dump.c:1062 +#, c-format +msgid " --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr " --include-foreign-data=ШАБЛОН\n" +" включають дані підлеглих таблиць на підлеглих\n" +" сервери, що відповідають ШАБЛОНУ\n" + +#: pg_dump.c:1065 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts вивантажити дані у вигляді команд INSERT, не COPY\n" + +#: pg_dump.c:1066 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root завантажувати секції через головну таблицю\n" + +#: pg_dump.c:1067 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments не вивантажувати коментарі\n" + +#: pg_dump.c:1068 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications не вивантажувати публікації\n" + +#: pg_dump.c:1069 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels не вивантажувати завдання міток безпеки\n" + +#: pg_dump.c:1070 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions не вивантажувати підписки\n" + +#: pg_dump.c:1071 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots не використовувати синхронізовані знімки в паралельних завданнях\n" + +#: pg_dump.c:1072 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces не вивантажувати призначення табличних просторів\n" + +#: pg_dump.c:1073 pg_dumpall.c:658 +#, c-format +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression не вивантажувати методи стиснення TOAST\n" + +#: pg_dump.c:1074 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data не вивантажувати дані таблиць, які не журналюються\n" + +#: pg_dump.c:1075 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing додавати ON CONFLICT DO NOTHING до команди INSERT\n" + +#: pg_dump.c:1076 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers укладати в лапки всі ідентифікатори, а не тільки ключові слова\n" + +#: pg_dump.c:1077 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS кількість рядків для INSERT; вимагає параметру --inserts\n" + +#: pg_dump.c:1078 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION вивантажити вказану секцію (pre-data, data або post-data)\n" + +#: pg_dump.c:1079 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable чекати коли вивантаження можна буде виконати без аномалій\n" + +#: pg_dump.c:1080 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT використовувати під час вивантаження вказаний знімок\n" + +#: pg_dump.c:1081 pg_restore.c:504 +#, c-format +msgid " --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr " --strict-names потребувати, щоб при вказівці шаблону включення\n" +" таблиці і/або схеми йому відповідав мінімум один об'єкт\n" + +#: pg_dump.c:1083 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid " --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr " --use-set-session-authorization\n" +" щоб встановити власника, використати команди SET SESSION AUTHORIZATION,\n" +" замість команд ALTER OWNER\n" + +#: pg_dump.c:1087 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "\n" +"Connection options:\n" +msgstr "\n" +"Налаштування з'єднання:\n" + +#: pg_dump.c:1088 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME ім'я бази даних для вивантаження\n" + +#: pg_dump.c:1089 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME хост серверу баз даних або каталог сокетів\n" + +#: pg_dump.c:1090 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=PORT номер порту сервера бази даних\n" + +#: pg_dump.c:1091 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=NAME підключатись як вказаний користувач бази даних\n" + +#: pg_dump.c:1092 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password ніколи не запитувати пароль\n" + +#: pg_dump.c:1093 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password запитувати пароль завжди (повинно траплятись автоматично)\n" + +#: pg_dump.c:1094 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME виконати SET ROLE до вивантаження\n" + +#: pg_dump.c:1096 +#, c-format +msgid "\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n\n" +msgstr "\n" +"Якщо ім'я бази даних не вказано, тоді використовується значення змінної середовища PGDATABASE.\n\n" + +#: pg_dump.c:1098 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Повідомляти про помилки на <%s>.\n" + +#: pg_dump.c:1099 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашня сторінка %s: <%s>\n" + +#: pg_dump.c:1118 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "вказано неприпустиме клієнтське кодування \"%s\"" + +#: pg_dump.c:1264 +#, c-format +msgid "Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "Синхронізовані знімки на резервному сервері не підтримуються цією версією сервера. Запустіть із параметром --no-synchronized-snapshots, якщо вам не потрібні синхронізовані знімки." + +#: pg_dump.c:1333 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "вказано неприпустимий формат виводу \"%s\"" + +#: pg_dump.c:1374 pg_dump.c:1430 pg_dump.c:1483 pg_dumpall.c:1451 +#, c-format +msgid "improper qualified name (too many dotted names): %s" +msgstr "неправильне повне ім'я (забагато компонентів): %s" + +#: pg_dump.c:1382 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "не знайдено відповідних схем для візерунку \"%s\"" + +#: pg_dump.c:1435 +#, c-format +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "не знайдено відповідних розширень для шаблону \"%s\"" + +#: pg_dump.c:1488 +#, c-format +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "не знайдено відповідних підлеглих серверів для шаблону \"%s\"" + +#: pg_dump.c:1551 +#, c-format +msgid "improper relation name (too many dotted names): %s" +msgstr "неправильне ім'я зв'язку (забагато компонентів): %s" + +#: pg_dump.c:1562 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "не знайдено відповідних таблиць для візерунку\"%s\"" + +#: pg_dump.c:1589 +#, c-format +msgid "You are currently not connected to a database." +msgstr "На даний момент ви від'єднанні від бази даних." + +#: pg_dump.c:1592 +#, c-format +msgid "cross-database references are not implemented: %s" +msgstr "міжбазові посилання не реалізовані: %s" + +#: pg_dump.c:2004 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "вивантажування змісту таблиці \"%s.%s\"" + +#: pg_dump.c:2111 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "Помилка вивантажування змісту таблиці \"%s\": помилка в PQgetCopyData()." + +#: pg_dump.c:2112 pg_dump.c:2122 +#, c-format +msgid "Error message from server: %s" +msgstr "Повідомлення про помилку від сервера: %s" + +#: pg_dump.c:2113 pg_dump.c:2123 +#, c-format +msgid "The command was: %s" +msgstr "Команда була: %s" + +#: pg_dump.c:2121 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "Помилка вивантажування змісту таблиці \"%s\": помилка в PQgetResult(). " + +#: pg_dump.c:2203 +#, c-format +msgid "wrong number of fields retrieved from table \"%s\"" +msgstr "неправильна кількість полів отриманих з таблиці \"%s\"" + +#: pg_dump.c:2916 +#, c-format +msgid "saving database definition" +msgstr "збереження визначення бази даних" + +#: pg_dump.c:3388 +#, c-format +msgid "saving encoding = %s" +msgstr "збереження кодування = %s" + +#: pg_dump.c:3413 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "збереження standard_conforming_strings = %s" + +#: pg_dump.c:3452 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "не вдалося проаналізувати результат current_schemas()" + +#: pg_dump.c:3471 +#, c-format +msgid "saving search_path = %s" +msgstr "збереження search_path = %s" + +#: pg_dump.c:3511 +#, c-format +msgid "reading large objects" +msgstr "читання великих об’єктів" + +#: pg_dump.c:3693 +#, c-format +msgid "saving large objects" +msgstr "збереження великих об’єктів" + +#: pg_dump.c:3739 +#, c-format +msgid "error reading large object %u: %s" +msgstr "помилка читання великих об’єктів %u: %s" + +#: pg_dump.c:3823 +#, c-format +msgid "reading row-level security policies" +msgstr "читання політик безпеки на рівні рядків" + +#: pg_dump.c:3966 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "неочікуваний тип команди в політиці: %c" + +#: pg_dump.c:4120 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "власник публікації \"%s\" здається недійсним" + +#: pg_dump.c:4412 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "підписки не вивантажені через те, що чинний користувач не є суперкористувачем" + +#: pg_dump.c:4483 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "власник підписки \"%s\" є недійсним" + +#: pg_dump.c:4526 +#, c-format +msgid "could not parse subpublications array" +msgstr "не вдалося аналізувати масив підпублікацій" + +#: pg_dump.c:4884 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "не вдалося знайти батьківський елемент для %s %s" + +#: pg_dump.c:5016 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "власник схеми \"%s\" виглядає недійсним" + +#: pg_dump.c:5039 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "схема з OID %u не існує" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "власник типу даних \"%s\" здається недійсним" + +#: pg_dump.c:5453 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "власник оператора \"%s\" здається недійсним" + +#: pg_dump.c:5752 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "власник класу операторів \"%s\" здається недійсним" + +#: pg_dump.c:5835 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "власник сімейства операторів \"%s\" здається недійсним" + +#: pg_dump.c:6003 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "власник агрегатної функції \"%s\" є недійсним" + +#: pg_dump.c:6262 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "власник функції \"%s\" здається недійсним" + +#: pg_dump.c:7089 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "власник таблиці \"%s\" здається недійсним" + +#: pg_dump.c:7131 pg_dump.c:17564 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "помилка цілісності, за OID %u не вдалося знайти батьківську таблицю послідовності з OID %u" + +#: pg_dump.c:7270 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "читання індексів таблиці \"%s.%s\"" + +#: pg_dump.c:7684 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "читання обмежень зовнішніх ключів таблиці \"%s.%s\"" + +#: pg_dump.c:7963 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "помилка цілісності, за OID %u не вдалося знайти батьківську таблицю для запису pg_rewrite з OID %u" + +#: pg_dump.c:8047 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "читання тригерів таблиці \"%s.%s\"" + +#: pg_dump.c:8229 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "запит не повернув ім'я цільової таблиці для тригера зовнішнього ключа \"%s\" в таблиці \"%s\" (OID цільової таблиці: %u)" + +#: pg_dump.c:8779 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "пошук стовпців і типів таблиці \"%s.%s\"" + +#: pg_dump.c:8903 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "неприпустима нумерація стовпців у таблиці \"%s\"" + +#: pg_dump.c:8942 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "пошук виразів за замовчуванням для таблиці \"%s.%s\"" + +#: pg_dump.c:8964 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "неприпустиме значення adnum %d для таблиці \"%s\"" + +#: pg_dump.c:9057 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "пошук обмежень-перевірок для таблиці \"%s.%s\"" + +#: pg_dump.c:9106 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "очікувалось %d обмеження-перевірка для таблиці \"%s\", але знайдено %d" +msgstr[1] "очікувалось %d обмеження-перевірки для таблиці \"%s\", але знайдено %d" +msgstr[2] "очікувалось %d обмежень-перевірок для таблиці \"%s\", але знайдено %d" +msgstr[3] "очікувалось %d обмежень-перевірок для таблиці \"%s\", але знайдено %d" + +#: pg_dump.c:9110 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(Можливо, системні каталоги пошкоджені.)" + +#: pg_dump.c:10712 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "typtype типу даних \"%s\" має неприпустимий вигляд" + +#: pg_dump.c:12060 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "неприпустиме значення в масиві proargmodes" + +#: pg_dump.c:12362 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "не вдалося аналізувати масив proallargtypes" + +#: pg_dump.c:12378 +#, c-format +msgid "could not parse proargmodes array" +msgstr "не вдалося аналізувати масив proargmodes" + +#: pg_dump.c:12392 +#, c-format +msgid "could not parse proargnames array" +msgstr "не вдалося аналізувати масив proargnames" + +#: pg_dump.c:12402 +#, c-format +msgid "could not parse proconfig array" +msgstr "не вдалося аналізувати масив proconfig" + +#: pg_dump.c:12478 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "нерозпізнане значення provolatile для функції \"%s\"" + +#: pg_dump.c:12528 pg_dump.c:14469 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "нерозпізнане значення proparallel для функції \"%s\"" + +#: pg_dump.c:12667 pg_dump.c:12773 pg_dump.c:12780 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "не вдалося знайти визначення функції для функції з OID %u" + +#: pg_dump.c:12706 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "неприпустиме значення в полі pg_cast.castfunc або pg_cast.castmethod" + +#: pg_dump.c:12709 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "неприпустиме значення в полі pg_cast.castmethod" + +#: pg_dump.c:12799 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "неприпустиме визначення перетворення, як мінімум одне з trffromsql і trftosql повинно бути ненульовим" + +#: pg_dump.c:12816 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "неприпустиме значення в полі pg_transform.trffromsql" + +#: pg_dump.c:12837 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "неприпустиме значення в полі pg_transform.trftosql" + +#: pg_dump.c:12988 +#, c-format +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "постфіксні оператори більше не підтримуються (оператор \"%s\")" + +#: pg_dump.c:13158 +#, c-format +msgid "could not find operator with OID %s" +msgstr "не вдалося знайти оператора з OID %s" + +#: pg_dump.c:13226 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "неприпустимий тип \"%c\" методу доступу \"%s\"" + +#: pg_dump.c:13980 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "нерозпізнаний постачальник правил сортування: %s" + +#: pg_dump.c:14388 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "нерозпізнане значення aggfinalmodify для агрегату \"%s\"" + +#: pg_dump.c:14444 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "нерозпізнане значення aggmfinalmodify для агрегату \"%s\"" + +#: pg_dump.c:15166 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "нерозпізнаний тип об’єкта у стандартному праві: %d" + +#: pg_dump.c:15184 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "не вдалося проаналізувати стандартний ACL список (%s)" + +#: pg_dump.c:15269 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "не вдалося аналізувати початковий список GRANT ACL (%s) або початковий список REVOKE ACL (%s) для об'єкта \"%s\" (%s)" + +#: pg_dump.c:15277 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "не вдалося аналізувати список GRANT ACL (%s) або список REVOKE ACL (%s) для об'єкта \"%s\" (%s)" + +#: pg_dump.c:15792 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "запит на отримання визначення перегляду \"%s\" не повернув дані" + +#: pg_dump.c:15795 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "запит на отримання визначення перегляду \"%s\" повернув більше, ніж одне визначення" + +#: pg_dump.c:15802 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "визначення перегляду \"%s\" пусте (довжина нуль)" + +#: pg_dump.c:15886 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "WITH OIDS більше не підтримується (таблиця\"%s\")" + +#: pg_dump.c:16751 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "неприпустиме число стовпців %d для таблиці \"%s\"" + +#: pg_dump.c:16828 +#, c-format +msgid "could not parse index statistic columns" +msgstr "не вдалося проаналізувати стовпці статистики індексів" + +#: pg_dump.c:16830 +#, c-format +msgid "could not parse index statistic values" +msgstr "не вдалося проаналізувати значення статистики індексів" + +#: pg_dump.c:16832 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "невідповідна кількість стовпців і значень для статистики індексів" + +#: pg_dump.c:17049 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "пропущено індекс для обмеження \"%s\"" + +#: pg_dump.c:17274 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "нерозпізнаний тип обмеження: %c" + +#: pg_dump.c:17406 pg_dump.c:17629 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "запит на отримання даних послідовності \"%s\" повернув %d рядки (очікувалося 1)" +msgstr[1] "запит на отримання даних послідовності \"%s\" повернув %d рядки (очікувалося 1)" +msgstr[2] "запит на отримання даних послідовності \"%s\" повернув %d рядків (очікувалося 1)" +msgstr[3] "запит на отримання даних послідовності \"%s\" повернув %d рядків (очікувалося 1)" + +#: pg_dump.c:17440 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "нерозпізнаний тип послідовності: %s" + +#: pg_dump.c:17727 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "неочікуване значення tgtype: %d" + +#: pg_dump.c:17801 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "неприпустимий рядок аргументу (%s) для тригера \"%s\" у таблиці \"%s\"" + +#: pg_dump.c:18070 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "помилка запиту на отримання правила \"%s\" для таблиці \"%s\": повернено неправильне число рядків " + +#: pg_dump.c:18232 +#, c-format +msgid "could not find referenced extension %u" +msgstr "не вдалося знайти згадане розширення %u" + +#: pg_dump.c:18323 +#, c-format +msgid "could not parse extension configuration array" +msgstr "не вдалося проаналізувати масив конфігурації розширення" + +#: pg_dump.c:18325 +#, c-format +msgid "could not parse extension condition array" +msgstr "не вдалося проаналізувати масив умов розширення" + +#: pg_dump.c:18327 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "невідповідна кількість конфігурацій і умов для розширення" + +#: pg_dump.c:18459 +#, c-format +msgid "reading dependency data" +msgstr "читання даних залежності" + +#: pg_dump.c:18552 +#, c-format +msgid "no referencing object %u %u" +msgstr "немає об’єкту посилання %u %u" + +#: pg_dump.c:18563 +#, c-format +msgid "no referenced object %u %u" +msgstr "немає посилання на об'єкт %u %u" + +#: pg_dump.c:18952 +#, c-format +msgid "could not parse reloptions array" +msgstr "неможливо розібрати масив reloptions" + +#: pg_dump_sort.c:420 +#, c-format +msgid "invalid dumpId %d" +msgstr "неприпустимий dumpId %d" + +#: pg_dump_sort.c:426 +#, c-format +msgid "invalid dependency %d" +msgstr "неприпустима залежність %d" + +#: pg_dump_sort.c:659 +#, c-format +msgid "could not identify dependency loop" +msgstr "не вдалося ідентифікувати цикл залежності" + +#: pg_dump_sort.c:1230 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "у наступній таблиці зациклені зовнішні ключі:" +msgstr[1] "у наступних таблицях зациклені зовнішні ключі:" +msgstr[2] "у наступних таблицях зациклені зовнішні ключі:" +msgstr[3] "у наступних таблицях зациклені зовнішні ключі:" + +#: pg_dump_sort.c:1234 pg_dump_sort.c:1254 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1235 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "Ви не зможете відновити дамп без використання --disable-triggers або тимчасово розірвати обмеження." + +#: pg_dump_sort.c:1236 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "Можливо, використання повного вивантажування замість --data-only вивантажування допоможе уникнути цієї проблеми." + +#: pg_dump_sort.c:1248 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "не вдалося вирішити цикл залежності серед цих елементів:" + +#: pg_dumpall.c:202 +#, c-format +msgid "The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "Програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\".\n" +"Перевірте вашу установку." + +#: pg_dumpall.c:207 +#, c-format +msgid "The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "Програма \"%s\" була знайдена \"%s\", але не була тієї ж версії, що %s.\n" +"Перевірте вашу установку." + +#: pg_dumpall.c:359 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "параметр --exclude-database не можна використовувати разом з -g/--globals-only, -r/--roles-only або -t/--tablespaces-only" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "параметри -g/--globals-only і -r/--roles-only не можна використовувати разом" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "параметри -g/--globals-only і -t/--tablespaces-only не можна використовувати разом" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "параметри -r/--roles-only і -t/--tablespaces-only не можна використовувати разом" + +#: pg_dumpall.c:453 pg_dumpall.c:1767 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "не вдалося зв'язатися з базою даних \"%s\"" + +#: pg_dumpall.c:467 +#, c-format +msgid "could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "не вдалося зв'язатися з базами даних \"postgres\" або \"template1\"\n" +"Будь ласка, вкажіть альтернативну базу даних." + +#: pg_dumpall.c:621 +#, c-format +msgid "%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +msgstr "%s експортує кластер баз даних PostgreSQL до SQL-скрипту.\n\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s: [OPTION]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=FILENAME ім'я вихідного файлу\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean очистити (видалити) бази даних перед відтворенням\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only вивантажувати лише глобальні об’єкти, не бази даних\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner пропускається відновлення форми власності об’єктом\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only вивантажувати лише ролі, не бази даних або табличні простори\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME ім'я суперкористувача для використання при вивантажуванні\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only вивантажувати лише табличні простори, не бази даних або ролі\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=PATTERN виключити бази даних, ім'я яких відповідає PATTERN\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords не вивантажувати паролі для ролей\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR підключення з використанням рядку підключення \n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME альтернативна база даних за замовчуванням\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n\n" +msgstr "\n" +"Якщо -f/--file не використовується, тоді SQL- сценарій буде записаний до стандартного виводу.\n\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "пропущено ім’я ролі, що починається з \"pg_\" (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "не вдалося аналізувати список ACL (%s) для табличного простору \"%s\"" + +#: pg_dumpall.c:1512 +#, c-format +msgid "excluding database \"%s\"" +msgstr "виключаємо базу даних \"%s\"" + +#: pg_dumpall.c:1516 +#, c-format +msgid "dumping database \"%s\"" +msgstr "вивантажуємо базу даних \"%s\"" + +#: pg_dumpall.c:1548 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "помилка pg_dump для бази даних \"%s\", завершення роботи" + +#: pg_dumpall.c:1557 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "не вдалося повторно відкрити файл виводу \"%s\": %m" + +#: pg_dumpall.c:1601 +#, c-format +msgid "running \"%s\"" +msgstr "виконується \"%s\"" + +#: pg_dumpall.c:1816 +#, c-format +msgid "could not get server version" +msgstr "не вдалося отримати версію серверу" + +#: pg_dumpall.c:1822 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "не вдалося аналізувати версію серверу \"%s\"" + +#: pg_dumpall.c:1894 pg_dumpall.c:1917 +#, c-format +msgid "executing %s" +msgstr "виконується %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "необхідно вказати один з -d/--dbname або -f/--file" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "параметри -d/--dbname і -f/--file не можуть використовуватись разом" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "параметри -C/--create і -1/--single-transaction не можуть використовуватись разом" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "максимальна кількість паралельних завдань: %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "параметр --single-transaction допускається лише з одним завданням" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "нерозпізнаний формат архіву \"%s\"; будь ласка, вкажіть \"c\", \"d\" або \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "при відновленні проігноровано помилок: %d" + +#: pg_restore.c:461 +#, c-format +msgid "%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +msgstr "%s відновлює базу даних PostgreSQL з архіву, створеного командою pg_dump.\n\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [OPTION]... [FILE]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=NAME підключитись до вказаної бази даних\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=FILENAME ім'я файлу виводу (- для stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t формат файлу резервної копії (розпізнається автоматично)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list вивести короткий зміст архіву\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose детальний режим\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію, потім вийти\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку, потім вийти\n" + +#: pg_restore.c:474 +#, c-format +msgid "\n" +"Options controlling the restore:\n" +msgstr "\n" +"Параметри, що керують відновленням:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only відновити лише дані, без схеми\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create створити цільову базу даних\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error вийти при помилці, продовжувати за замовчуванням\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME відновити вказаний індекс\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM щоб виконати відновлення, використайте ці паралельні завдання\n" + +#: pg_restore.c:481 +#, c-format +msgid " -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr " -L, --use-list=FILENAME використовувати зміст з цього файлу для \n" +" вибору/упорядкування даних\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME відновити об'єкти лише в цій схемі\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME не відновлювати об'єкти в цій схемі\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) відновити вказану функцію\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only відновити лише схему, без даних\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAME ім'я суперкористувача для вимкнення тригерів\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NAME відновити вказане відношення (таблицю, подання і т. д.)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAME відновити вказаний тригер\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges пропустити відновлення прав доступу (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction відновити в одній транзакції\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security активувати захист на рівні рядків\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments не відновлювати коментарі\n" + +#: pg_restore.c:497 +#, c-format +msgid " --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr " --no-data-for-failed-tables не відновлювати дані таблиць, які не вдалося створити\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications не відновлювати публікації \n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels не відновлювати мітки безпеки \n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions не відновлювати підписки\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces не відновлювати завдання табличного простору\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION відновлювати названий розділ (pre-data, data або post-data)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME виконати SET ROLE перед відновленням\n" + +#: pg_restore.c:518 +#, c-format +msgid "\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "\n" +"Параметри -I, -n, -N, -P, -t, -T, і --section можна групувати і вказувати\n" +"декілька разів для вибору декількох об'єктів.\n" + +#: pg_restore.c:521 +#, c-format +msgid "\n" +"If no input file name is supplied, then standard input is used.\n\n" +msgstr "\n" +"Якщо ім'я файлу введеня не вказано, тоді використовується стандартне введення.\n\n" + diff --git a/src/bin/pg_dump/po/zh_CN.po b/src/bin/pg_dump/po/zh_CN.po new file mode 100644 index 0000000..a580c50 --- /dev/null +++ b/src/bin/pg_dump/po/zh_CN.po @@ -0,0 +1,2643 @@ +# simplified Chinese translation file for pg_dump and friends +# Weiping He , 2001. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_dump (PostgreSQL) 14\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2021-08-14 05:48+0000\n" +"PO-Revision-Date: 2021-08-15 18:00+0800\n" +"Last-Translator: Jie Zhang \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.7\n" + +#: ../../../src/common/logging.c:259 +#, c-format +msgid "fatal: " +msgstr "致命的: " + +#: ../../../src/common/logging.c:266 +#, c-format +msgid "error: " +msgstr "错误: " + +#: ../../../src/common/logging.c:273 +#, c-format +msgid "warning: " +msgstr "警告: " + +#: ../../common/exec.c:136 ../../common/exec.c:253 ../../common/exec.c:299 +#, c-format +msgid "could not identify current directory: %m" +msgstr "无法确认当前目录: %m" + +#: ../../common/exec.c:155 +#, c-format +msgid "invalid binary \"%s\"" +msgstr "无效的二进制码 \"%s\"" + +#: ../../common/exec.c:205 +#, c-format +msgid "could not read binary \"%s\"" +msgstr "无法读取二进制码 \"%s\"" + +#: ../../common/exec.c:213 +#, c-format +msgid "could not find a \"%s\" to execute" +msgstr "未能找到一个 \"%s\" 来执行" + +#: ../../common/exec.c:269 ../../common/exec.c:308 +#, c-format +msgid "could not change directory to \"%s\": %m" +msgstr "无法跳转到目录 \"%s\" 中: %m" + +#: ../../common/exec.c:286 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "无法读取符号链接 \"%s\": %m" + +#: ../../common/exec.c:409 parallel.c:1614 +msgid "%s() failed: %m" +msgstr "%s()失败: %m" + +#: ../../common/exec.c:522 ../../common/exec.c:567 ../../common/exec.c:659 +msgid "out of memory" +msgstr "内存不足" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#, c-format +msgid "out of memory\n" +msgstr "内存不足\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "无法复制空指针 (内部错误)\n" + +#: ../../common/wait_error.c:45 +#, c-format +msgid "command not executable" +msgstr "命令无法执行" + +#: ../../common/wait_error.c:49 +#, c-format +msgid "command not found" +msgstr "命令没有找到" + +#: ../../common/wait_error.c:54 +#, c-format +msgid "child process exited with exit code %d" +msgstr "子进程已退出, 退出码为 %d" + +#: ../../common/wait_error.c:62 +#, c-format +msgid "child process was terminated by exception 0x%X" +msgstr "子进程被例外(exception) 0x%X 终止" + +#: ../../common/wait_error.c:66 +#, c-format +msgid "child process was terminated by signal %d: %s" +msgstr "子进程被信号 %d 终止: %s" + +#: ../../common/wait_error.c:72 +#, c-format +msgid "child process exited with unrecognized status %d" +msgstr "子进程已退出, 未知状态 %d" + +#: common.c:124 +#, c-format +msgid "reading extensions" +msgstr "读扩展" + +#: common.c:128 +#, c-format +msgid "identifying extension members" +msgstr "识别扩展成员" + +#: common.c:131 +#, c-format +msgid "reading schemas" +msgstr "读取模式" + +#: common.c:141 +#, c-format +msgid "reading user-defined tables" +msgstr "读取用户定义表" + +#: common.c:148 +#, c-format +msgid "reading user-defined functions" +msgstr "读取用户定义函数" + +#: common.c:153 +#, c-format +msgid "reading user-defined types" +msgstr "读取用户定义类型" + +#: common.c:158 +#, c-format +msgid "reading procedural languages" +msgstr "读取过程语言" + +#: common.c:161 +#, c-format +msgid "reading user-defined aggregate functions" +msgstr "读取用户定义聚集函数" + +#: common.c:164 +#, c-format +msgid "reading user-defined operators" +msgstr "读取用户定义操作符" + +#: common.c:168 +#, c-format +msgid "reading user-defined access methods" +msgstr "读取用户定义的访问方法" + +#: common.c:171 +#, c-format +msgid "reading user-defined operator classes" +msgstr "读取用户定义操作符集" + +#: common.c:174 +#, c-format +msgid "reading user-defined operator families" +msgstr "读取用户定义操作符" + +#: common.c:177 +#, c-format +msgid "reading user-defined text search parsers" +msgstr "读取用户定义的文本搜索解析器" + +#: common.c:180 +#, c-format +msgid "reading user-defined text search templates" +msgstr "读取用户定义的文本搜索模板" + +#: common.c:183 +#, c-format +msgid "reading user-defined text search dictionaries" +msgstr "读取用户定义的文本搜索字典" + +#: common.c:186 +#, c-format +msgid "reading user-defined text search configurations" +msgstr "读取用户定义的文本搜索配置" + +#: common.c:189 +#, c-format +msgid "reading user-defined foreign-data wrappers" +msgstr "读取用户定义外部数据封装器" + +#: common.c:192 +#, c-format +msgid "reading user-defined foreign servers" +msgstr "读取用户定义的外部服务器" + +#: common.c:195 +#, c-format +msgid "reading default privileges" +msgstr "正在读取缺省权限" + +#: common.c:198 +#, c-format +msgid "reading user-defined collations" +msgstr "读取用户定义的校对函数" + +#: common.c:202 +#, c-format +msgid "reading user-defined conversions" +msgstr "读取用户定义的字符集转换" + +#: common.c:205 +#, c-format +msgid "reading type casts" +msgstr "读取类型转换" + +#: common.c:208 +#, c-format +msgid "reading transforms" +msgstr "读取转换" + +#: common.c:211 +#, c-format +msgid "reading table inheritance information" +msgstr "读取表继承信息" + +#: common.c:214 +#, c-format +msgid "reading event triggers" +msgstr "读取事件触发器" + +#: common.c:218 +#, c-format +msgid "finding extension tables" +msgstr "查找扩展表" + +#: common.c:222 +#, c-format +msgid "finding inheritance relationships" +msgstr "正在查找关系继承" + +#: common.c:225 +#, c-format +msgid "reading column info for interesting tables" +msgstr "正在读取感兴趣表的列信息" + +#: common.c:228 +#, c-format +msgid "flagging inherited columns in subtables" +msgstr "在子表里标记继承字段" + +#: common.c:231 +#, c-format +msgid "reading indexes" +msgstr "读取索引" + +#: common.c:234 +#, c-format +msgid "flagging indexes in partitioned tables" +msgstr "在分区表中标记索引" + +#: common.c:237 +#, c-format +msgid "reading extended statistics" +msgstr "读取扩展统计信息" + +#: common.c:240 +#, c-format +msgid "reading constraints" +msgstr "读取约束" + +#: common.c:243 +#, c-format +msgid "reading triggers" +msgstr "读取触发器" + +#: common.c:246 +#, c-format +msgid "reading rewrite rules" +msgstr "读取重写规则" + +#: common.c:249 +#, c-format +msgid "reading policies" +msgstr "读取策略" + +#: common.c:252 +#, c-format +msgid "reading publications" +msgstr "读取发布" + +#: common.c:257 +#, c-format +msgid "reading publication membership" +msgstr "读取发布成员资格" + +#: common.c:260 +#, c-format +msgid "reading subscriptions" +msgstr "读取订阅" + +#: common.c:338 +#, c-format +msgid "invalid number of parents %d for table \"%s\"" +msgstr "表 \"%2$s\" 的无效parents值 %1$d" + +#: common.c:1100 +#, c-format +msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +msgstr "健全检查失败, 未找到表 \"%2$s\" (OID %3$u) 的 OID 为 %1$u 的父辈" + +#: common.c:1142 +#, c-format +msgid "could not parse numeric array \"%s\": too many numbers" +msgstr "无法分析数值数组\"%s\": 数字太多" + +#: common.c:1157 +#, c-format +msgid "could not parse numeric array \"%s\": invalid character in number" +msgstr "无法分析数值数组\"%s\": 出现无效字符" + +#: compress_io.c:111 +#, c-format +msgid "invalid compression code: %d" +msgstr "无效的压缩码: %d" + +#: compress_io.c:134 compress_io.c:170 compress_io.c:188 compress_io.c:504 +#: compress_io.c:547 +#, c-format +msgid "not built with zlib support" +msgstr "没有编译成带有zlib库支持的版本" + +#: compress_io.c:236 compress_io.c:333 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "无法初始化压缩库: %s" + +#: compress_io.c:256 +#, c-format +msgid "could not close compression stream: %s" +msgstr "无法关闭压缩流: %s" + +#: compress_io.c:273 +#, c-format +msgid "could not compress data: %s" +msgstr "无法压缩数据: %s" + +#: compress_io.c:349 compress_io.c:364 +#, c-format +msgid "could not uncompress data: %s" +msgstr "无法解压缩数据: %s" + +#: compress_io.c:371 +#, c-format +msgid "could not close compression library: %s" +msgstr "无法关闭压缩库: %s" + +#: compress_io.c:584 compress_io.c:621 pg_backup_tar.c:551 pg_backup_tar.c:554 +#, c-format +msgid "could not read from input file: %s" +msgstr "无法从输入档案读取:%s" + +#: compress_io.c:623 pg_backup_custom.c:643 pg_backup_directory.c:552 +#: pg_backup_tar.c:787 pg_backup_tar.c:810 +#, c-format +msgid "could not read from input file: end of file" +msgstr "无法从输入文件中读取:文件的结尾" + +#: parallel.c:254 +msgid "%s() failed: error code %d" +msgstr "%s()失败: 错误码为 %d" + +#: parallel.c:964 +#, c-format +msgid "could not create communication channels: %m" +msgstr "无法创建通信通道: %m" + +#: parallel.c:1021 +#, c-format +msgid "could not create worker process: %m" +msgstr "无法创建工作进程: %m" + +#: parallel.c:1151 +msgid "unrecognized command received from leader: \"%s\"" +msgstr "从主机接收到无法识别的命令: \"%s\"" + +#: parallel.c:1194 parallel.c:1432 +#, c-format +msgid "invalid message received from worker: \"%s\"" +msgstr "接收到来自工作者进程的无效消息: \"%s\"" + +#: parallel.c:1326 +#, c-format +msgid "" +"could not obtain lock on relation \"%s\"\n" +"This usually means that someone requested an ACCESS EXCLUSIVE lock on the table after the pg_dump parent process had gotten the initial ACCESS SHARE lock on the table." +msgstr "" +"无法获取关系 \"%s\"上的锁\n" +"这通常意味着在父进程pg_dump已经得到表的共享访问锁之后,仍有人请求该表的排它访问锁." + +#: parallel.c:1415 +#, c-format +msgid "a worker process died unexpectedly" +msgstr "一工作者进程意外退出" + +#: parallel.c:1537 parallel.c:1655 +#, c-format +msgid "could not write to the communication channel: %m" +msgstr "无法写入通信通道: %m" + +#: parallel.c:1739 +#, c-format +msgid "pgpipe: could not create socket: error code %d" +msgstr "pgpipe: 无法创建套接字: 错误码为 %d" + +#: parallel.c:1750 +#, c-format +msgid "pgpipe: could not bind: error code %d" +msgstr "pgpipe: 无法绑定: 错误码为%d" + +#: parallel.c:1757 +#, c-format +msgid "pgpipe: could not listen: error code %d" +msgstr "pgpipe: 无法监听: 错误码为 %d" + +#: parallel.c:1764 +msgid "pgpipe: %s() failed: error code %d" +msgstr "pgpipe: %s()失败: 错误码为 %d" + +#: parallel.c:1775 +#, c-format +msgid "pgpipe: could not create second socket: error code %d" +msgstr "pgpipe: 无法创建继承套接字: 错误码为 %d" + +#: parallel.c:1784 +#, c-format +msgid "pgpipe: could not connect socket: error code %d" +msgstr "pgpipe: 无法连接套接字: 错误码为 %d" + +#: parallel.c:1793 +#, c-format +msgid "pgpipe: could not accept connection: error code %d" +msgstr "pgpipe: 无法接受连接: 错误码为 %d" + +#: pg_backup_archiver.c:277 pg_backup_archiver.c:1576 +#, c-format +msgid "could not close output file: %m" +msgstr "无法关闭输出文件: %m" + +#: pg_backup_archiver.c:321 pg_backup_archiver.c:325 +#, c-format +msgid "archive items not in correct section order" +msgstr "归档项的序号不正确" + +#: pg_backup_archiver.c:331 +#, c-format +msgid "unexpected section code %d" +msgstr "意外的节码 %d" + +#: pg_backup_archiver.c:368 +#, c-format +msgid "parallel restore is not supported with this archive file format" +msgstr "不支持以这种归档文件格式进行并行恢复" + +#: pg_backup_archiver.c:372 +#, c-format +msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" +msgstr "不支持使用8.0版本以前的pg_dump命令产生的存档文件进行并行恢复" + +#: pg_backup_archiver.c:390 +#, c-format +msgid "cannot restore from compressed archive (compression not supported in this installation)" +msgstr "无法从压缩的归档中恢复 (未配置压缩支持)" + +#: pg_backup_archiver.c:407 +#, c-format +msgid "connecting to database for restore" +msgstr "为恢复数据库与数据库联接" + +#: pg_backup_archiver.c:409 +#, c-format +msgid "direct database connections are not supported in pre-1.3 archives" +msgstr "1.3 以前的归档里不支持直接数据库联接" + +#: pg_backup_archiver.c:452 +#, c-format +msgid "implied data-only restore" +msgstr "隐含的只恢复数据" + +#: pg_backup_archiver.c:518 +#, c-format +msgid "dropping %s %s" +msgstr "删除 %s %s" + +#: pg_backup_archiver.c:613 +#, c-format +msgid "could not find where to insert IF EXISTS in statement \"%s\"" +msgstr "找不到要插入的位置,由于IF EXISTS在 \"%s\"状态" + +#: pg_backup_archiver.c:769 pg_backup_archiver.c:771 +#, c-format +msgid "warning from original dump file: %s" +msgstr "来自原始转储文件的警告: %s" + +#: pg_backup_archiver.c:786 +#, c-format +msgid "creating %s \"%s.%s\"" +msgstr "创建%s \"%s.%s\"" + +#: pg_backup_archiver.c:789 +#, c-format +msgid "creating %s \"%s\"" +msgstr "创建%s \"%s\"" + +#: pg_backup_archiver.c:839 +#, c-format +msgid "connecting to new database \"%s\"" +msgstr "联接到新数据库 \"%s\"" + +#: pg_backup_archiver.c:866 +#, c-format +msgid "processing %s" +msgstr "正在处理 %s" + +#: pg_backup_archiver.c:886 +#, c-format +msgid "processing data for table \"%s.%s\"" +msgstr "为表\"%s.%s\"处理数据" + +#: pg_backup_archiver.c:948 +#, c-format +msgid "executing %s %s" +msgstr "执行 %s %s" + +#: pg_backup_archiver.c:987 +#, c-format +msgid "disabling triggers for %s" +msgstr "为%s禁用触发器" + +#: pg_backup_archiver.c:1013 +#, c-format +msgid "enabling triggers for %s" +msgstr "为%s启用触发器" + +#: pg_backup_archiver.c:1041 +#, c-format +msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" +msgstr "内部错误 -- WriteData 不能在 DataDumper 过程的环境之外调用" + +#: pg_backup_archiver.c:1224 +#, c-format +msgid "large-object output not supported in chosen format" +msgstr "选定的格式不支持大对象输出" + +#: pg_backup_archiver.c:1282 +#, c-format +msgid "restored %d large object" +msgid_plural "restored %d large objects" +msgstr[0] "恢复%d个大对象" +msgstr[1] "恢复%d个大对象" + +#: pg_backup_archiver.c:1303 pg_backup_tar.c:730 +#, c-format +msgid "restoring large object with OID %u" +msgstr "恢复带有OID %u 的大对象" + +#: pg_backup_archiver.c:1315 +#, c-format +msgid "could not create large object %u: %s" +msgstr "无法创建大对象%u: %s" + +#: pg_backup_archiver.c:1320 pg_dump.c:3638 +#, c-format +msgid "could not open large object %u: %s" +msgstr "无法打开大对象%u: %s" + +#: pg_backup_archiver.c:1376 +#, c-format +msgid "could not open TOC file \"%s\": %m" +msgstr "无法打开TOC文件 \"%s\": %m" + +#: pg_backup_archiver.c:1404 +#, c-format +msgid "line ignored: %s" +msgstr "忽略的行: %s" + +#: pg_backup_archiver.c:1411 +#, c-format +msgid "could not find entry for ID %d" +msgstr "无法为 ID %d 找到记录" + +#: pg_backup_archiver.c:1434 pg_backup_directory.c:222 +#: pg_backup_directory.c:598 +#, c-format +msgid "could not close TOC file: %m" +msgstr "无法关闭 TOC 文件: %m" + +#: pg_backup_archiver.c:1548 pg_backup_custom.c:156 pg_backup_directory.c:332 +#: pg_backup_directory.c:585 pg_backup_directory.c:648 +#: pg_backup_directory.c:667 pg_dumpall.c:489 +#, c-format +msgid "could not open output file \"%s\": %m" +msgstr "无法打开输出文件\"%s\": %m" + +#: pg_backup_archiver.c:1550 pg_backup_custom.c:162 +#, c-format +msgid "could not open output file: %m" +msgstr "无法打开输出文件: %m" + +#: pg_backup_archiver.c:1643 +msgid "wrote %zu byte of large object data (result = %d)" +msgid_plural "wrote %zu bytes of large object data (result = %d)" +msgstr[0] "已经写入了大对象的%zu字节(结果 = %d)" +msgstr[1] "已经写入了大对象的%zu字节(结果 = %d)" + +#: pg_backup_archiver.c:1649 +msgid "could not write to large object: %s" +msgstr "无法写入大型对象: %s" + +#: pg_backup_archiver.c:1739 +#, c-format +msgid "while INITIALIZING:" +msgstr "INITIALIZING 时:" + +#: pg_backup_archiver.c:1744 +#, c-format +msgid "while PROCESSING TOC:" +msgstr "PROCESSING TOC 时:" + +#: pg_backup_archiver.c:1749 +#, c-format +msgid "while FINALIZING:" +msgstr "FINALIZING 时:" + +#: pg_backup_archiver.c:1754 +#, c-format +msgid "from TOC entry %d; %u %u %s %s %s" +msgstr "来自 TOC 记录 %d; %u %u %s %s %s" + +#: pg_backup_archiver.c:1830 +#, c-format +msgid "bad dumpId" +msgstr "错误的dumpId号" + +#: pg_backup_archiver.c:1851 +#, c-format +msgid "bad table dumpId for TABLE DATA item" +msgstr "TABLE DATA 项的表dumpId错误" + +#: pg_backup_archiver.c:1943 +#, c-format +msgid "unexpected data offset flag %d" +msgstr "意外的数据偏移标志 %d" + +#: pg_backup_archiver.c:1956 +#, c-format +msgid "file offset in dump file is too large" +msgstr "在转储文件中的文件偏移量太大" + +#: pg_backup_archiver.c:2094 pg_backup_archiver.c:2104 +#, c-format +msgid "directory name too long: \"%s\"" +msgstr "字典名字太长: \"%s\"" + +#: pg_backup_archiver.c:2112 +#, c-format +msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +msgstr "目录 \"%s\" 看上去不像一个有效的归档 (\"toc.dat\" 不存在)" + +#: pg_backup_archiver.c:2120 pg_backup_custom.c:173 pg_backup_custom.c:807 +#: pg_backup_directory.c:207 pg_backup_directory.c:394 +#, c-format +msgid "could not open input file \"%s\": %m" +msgstr "无法打开输入文件 \"%s\": %m" + +#: pg_backup_archiver.c:2127 pg_backup_custom.c:179 +#, c-format +msgid "could not open input file: %m" +msgstr "无法打开输入文件: %m" + +#: pg_backup_archiver.c:2133 +#, c-format +msgid "could not read input file: %m" +msgstr "无法读取输入文件: %m" + +#: pg_backup_archiver.c:2135 +#, c-format +msgid "input file is too short (read %lu, expected 5)" +msgstr "输入文件太短 (读了 %lu, 预期 5)" + +#: pg_backup_archiver.c:2167 +#, c-format +msgid "input file appears to be a text format dump. Please use psql." +msgstr "输入文件看起来像是文本格式的dump. 请使用psql." + +#: pg_backup_archiver.c:2173 +#, c-format +msgid "input file does not appear to be a valid archive (too short?)" +msgstr "输入文件看上去不象有效的归档 (太短?)" + +#: pg_backup_archiver.c:2179 +#, c-format +msgid "input file does not appear to be a valid archive" +msgstr "输入文件看上去不象有效的归档" + +#: pg_backup_archiver.c:2188 +#, c-format +msgid "could not close input file: %m" +msgstr "无法关闭输入文件: %m" + +#: pg_backup_archiver.c:2305 +#, c-format +msgid "unrecognized file format \"%d\"" +msgstr "不可识别的文件格式 \"%d\"" + +#: pg_backup_archiver.c:2387 pg_backup_archiver.c:4411 +#, c-format +msgid "finished item %d %s %s" +msgstr "已完成的成员%d %s %s" + +#: pg_backup_archiver.c:2391 pg_backup_archiver.c:4424 +#, c-format +msgid "worker process failed: exit code %d" +msgstr "子进程已退出, 退出码为 %d" + +#: pg_backup_archiver.c:2511 +#, c-format +msgid "entry ID %d out of range -- perhaps a corrupt TOC" +msgstr "记录 ID %d 超出范围 - 可能是损坏了的 TOC" + +#: pg_backup_archiver.c:2578 +#, c-format +msgid "restoring tables WITH OIDS is not supported anymore" +msgstr "不再支持使用OID还原表" + +#: pg_backup_archiver.c:2660 +#, c-format +msgid "unrecognized encoding \"%s\"" +msgstr "未知编码: \"%s\"" + +#: pg_backup_archiver.c:2665 +#, c-format +msgid "invalid ENCODING item: %s" +msgstr "无效的ENCODING成员:%s" + +#: pg_backup_archiver.c:2683 +#, c-format +msgid "invalid STDSTRINGS item: %s" +msgstr "无效的STDSTRINGS成员:%s" + +#: pg_backup_archiver.c:2708 +#, c-format +msgid "schema \"%s\" not found" +msgstr "模式\"%s\"没有找到" + +#: pg_backup_archiver.c:2715 +#, c-format +msgid "table \"%s\" not found" +msgstr "表\"%s\"没有找到" + +#: pg_backup_archiver.c:2722 +#, c-format +msgid "index \"%s\" not found" +msgstr "索引\"%s\"没有找到" + +#: pg_backup_archiver.c:2729 +#, c-format +msgid "function \"%s\" not found" +msgstr "函数\"%s\"没有找到" + +#: pg_backup_archiver.c:2736 +#, c-format +msgid "trigger \"%s\" not found" +msgstr "触发器\"%s\"没有找到" + +#: pg_backup_archiver.c:3128 +#, c-format +msgid "could not set session user to \"%s\": %s" +msgstr "无法设置会话用户为 \"%s\": %s" + +#: pg_backup_archiver.c:3260 +msgid "could not set search_path to \"%s\": %s" +msgstr "无法将search_path设置为\"%s\": %s" + +#: pg_backup_archiver.c:3322 +msgid "could not set default_tablespace to %s: %s" +msgstr "无法将default_tablespace设置为%s: %s" + +#: pg_backup_archiver.c:3367 +msgid "could not set default_table_access_method: %s" +msgstr "无法统设置default_table_access_method: %s" + +#: pg_backup_archiver.c:3459 pg_backup_archiver.c:3617 +#, c-format +msgid "don't know how to set owner for object type \"%s\"" +msgstr "不知道如何为对象类型\"%s\"设置属主" + +#: pg_backup_archiver.c:3720 +#, c-format +msgid "did not find magic string in file header" +msgstr "在文件头中没有找到魔术字串" + +#: pg_backup_archiver.c:3734 +#, c-format +msgid "unsupported version (%d.%d) in file header" +msgstr "在文件头中有不支持的版本 (%d.%d)" + +#: pg_backup_archiver.c:3739 +#, c-format +msgid "sanity check on integer size (%lu) failed" +msgstr "整数尺寸 (%lu) 的健全检查失败" + +#: pg_backup_archiver.c:3743 +#, c-format +msgid "archive was made on a machine with larger integers, some operations might fail" +msgstr "归档不是在支持更大范围整数的主机上产生的, 有些操作可能失败" + +#: pg_backup_archiver.c:3753 +#, c-format +msgid "expected format (%d) differs from format found in file (%d)" +msgstr "预期的格式 (%d) 和在文件里找到的格式 (%d) 不同" + +#: pg_backup_archiver.c:3768 +#, c-format +msgid "archive is compressed, but this installation does not support compression -- no data will be available" +msgstr "归档是压缩过的, 但是当前安装不支持压缩 -- 数据将不可使用" + +#: pg_backup_archiver.c:3802 +#, c-format +msgid "invalid creation date in header" +msgstr "在头中的创建日期无效" + +#: pg_backup_archiver.c:3936 +#, c-format +msgid "processing item %d %s %s" +msgstr "正在处理成员%d %s %s" + +#: pg_backup_archiver.c:4015 +#, c-format +msgid "entering main parallel loop" +msgstr "正在进入主并行循环" + +#: pg_backup_archiver.c:4026 +#, c-format +msgid "skipping item %d %s %s" +msgstr "忽略成员%d %s %s" + +#: pg_backup_archiver.c:4035 +#, c-format +msgid "launching item %d %s %s" +msgstr "正在启动成员%d %s %s" + +#: pg_backup_archiver.c:4089 +#, c-format +msgid "finished main parallel loop" +msgstr "已完成主并行循环" + +#: pg_backup_archiver.c:4125 +#, c-format +msgid "processing missed item %d %s %s" +msgstr "正在处理丢失的成员%d %s %s" + +#: pg_backup_archiver.c:4730 +#, c-format +msgid "table \"%s\" could not be created, will not restore its data" +msgstr "无法创建表\"%s\" , 这样无法恢复它的数据" + +#: pg_backup_custom.c:376 pg_backup_null.c:147 +#, c-format +msgid "invalid OID for large object" +msgstr "大对象的无效 OID" + +#: pg_backup_custom.c:439 pg_backup_custom.c:505 pg_backup_custom.c:629 +#: pg_backup_custom.c:865 pg_backup_tar.c:1080 pg_backup_tar.c:1085 +#, c-format +msgid "error during file seek: %m" +msgstr "在文件内定位时出错: %m" + +#: pg_backup_custom.c:478 +#, c-format +msgid "data block %d has wrong seek position" +msgstr "数据块%d的寻道位置错误" + +#: pg_backup_custom.c:495 +#, c-format +msgid "unrecognized data block type (%d) while searching archive" +msgstr "搜索归档是碰到不识别的数据块类型 (%d)" + +#: pg_backup_custom.c:517 +#, c-format +msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" +msgstr "在归档中无法找到数据块ID %d -- 这可能是由于不正常的恢复引起的,这种不正常的恢复通常因为缺少的输入文件而无法处理" + +#: pg_backup_custom.c:522 +#, c-format +msgid "could not find block ID %d in archive -- possibly corrupt archive" +msgstr "无法在归档中找到ID为%d的数据块--这可能是因为归档文件损坏" + +#: pg_backup_custom.c:529 +#, c-format +msgid "found unexpected block ID (%d) when reading data -- expected %d" +msgstr "读取数据时发现意外块 ID (%d) - 预期是 %d" + +#: pg_backup_custom.c:543 +#, c-format +msgid "unrecognized data block type %d while restoring archive" +msgstr "恢复归档时碰到不识别的数据块类型 %d" + +#: pg_backup_custom.c:645 +#, c-format +msgid "could not read from input file: %m" +msgstr "无法从输入档案读取:%m" + +#: pg_backup_custom.c:746 pg_backup_custom.c:798 pg_backup_custom.c:943 +#: pg_backup_tar.c:1083 +#, c-format +msgid "could not determine seek position in archive file: %m" +msgstr "无法在归档文件中确定查找位置: %m" + +#: pg_backup_custom.c:762 pg_backup_custom.c:802 +#, c-format +msgid "could not close archive file: %m" +msgstr "无法关闭归档文件: %m" + +#: pg_backup_custom.c:785 +#, c-format +msgid "can only reopen input archives" +msgstr "只能重新打开输入归档" + +#: pg_backup_custom.c:792 +#, c-format +msgid "parallel restore from standard input is not supported" +msgstr "不支持从标准输入进行并行恢复" + +#: pg_backup_custom.c:794 +#, c-format +msgid "parallel restore from non-seekable file is not supported" +msgstr "不支持从不可随机寻址的文件里并行恢复" + +#: pg_backup_custom.c:810 +#, c-format +msgid "could not set seek position in archive file: %m" +msgstr "无法在归档文件中设置查找位置: %m" + +#: pg_backup_custom.c:889 +#, c-format +msgid "compressor active" +msgstr "压缩程序已激活" + +#: pg_backup_db.c:42 +#, c-format +msgid "could not get server_version from libpq" +msgstr "无法从 libpq 获取服务器版本" + +#: pg_backup_db.c:53 pg_dumpall.c:1826 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "服务器版本: %s; %s 版本: %s" + +#: pg_backup_db.c:55 pg_dumpall.c:1828 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "因为服务器版本不匹配而终止" + +#: pg_backup_db.c:124 +#, c-format +msgid "already connected to a database" +msgstr "已经与一个数据库联接" + +#: pg_backup_db.c:132 pg_backup_db.c:182 pg_dumpall.c:1655 pg_dumpall.c:1766 +msgid "Password: " +msgstr "口令: " + +#: pg_backup_db.c:174 +msgid "could not connect to database" +msgstr "无法与数据库联接" + +#: pg_backup_db.c:191 +msgid "reconnection failed: %s" +msgstr "重新连接失败: %s" + +#: pg_backup_db.c:194 pg_backup_db.c:269 pg_dumpall.c:1686 pg_dumpall.c:1776 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_backup_db.c:276 pg_dumpall.c:1889 pg_dumpall.c:1912 +#, c-format +msgid "query failed: %s" +msgstr "查询失败: %s" + +#: pg_backup_db.c:278 pg_dumpall.c:1890 pg_dumpall.c:1913 +#, c-format +msgid "query was: %s" +msgstr "查询是: %s" + +#: pg_backup_db.c:319 +#, c-format +msgid "query returned %d row instead of one: %s" +msgid_plural "query returned %d rows instead of one: %s" +msgstr[0] "查询返回了%d条记录,而不是一条记录: %s" +msgstr[1] "查询返回了%d条记录,而不是一条记录: %s" + +#: pg_backup_db.c:355 +msgid "%s: %sCommand was: %s" +msgstr "%s: %s命令是: %s" + +#: pg_backup_db.c:411 pg_backup_db.c:485 pg_backup_db.c:492 +msgid "could not execute query" +msgstr "无法执行查询" + +#: pg_backup_db.c:464 +#, c-format +msgid "error returned by PQputCopyData: %s" +msgstr "PQputCopyData返回错误: %s" + +#: pg_backup_db.c:513 +#, c-format +msgid "error returned by PQputCopyEnd: %s" +msgstr "PQputCopyEnd返回错误: %s" + +#: pg_backup_db.c:519 +msgid "COPY failed for table \"%s\": %s" +msgstr "复制表\"%s\"失败: %s" + +#: pg_backup_db.c:525 pg_dump.c:2074 +#, c-format +msgid "unexpected extra results during COPY of table \"%s\"" +msgstr "复制表\"%s\"时出现意外的额外结果" + +#: pg_backup_db.c:537 +msgid "could not start database transaction" +msgstr "无法开始数据库事务" + +#: pg_backup_db.c:545 +msgid "could not commit database transaction" +msgstr "无法提交数据库事务" + +#: pg_backup_directory.c:156 +#, c-format +msgid "no output directory specified" +msgstr "没有指定输出目录" + +#: pg_backup_directory.c:185 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "无法读取目录 \"%s\": %m" + +#: pg_backup_directory.c:189 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "无法关闭目录 \"%s\": %m" + +#: pg_backup_directory.c:195 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "无法创建目录 \"%s\": %m" + +#: pg_backup_directory.c:355 pg_backup_directory.c:496 +#: pg_backup_directory.c:532 +#, c-format +msgid "could not write to output file: %s" +msgstr "无法写到输出文件: %s" + +#: pg_backup_directory.c:406 +msgid "could not close data file \"%s\": %m" +msgstr "无法关闭数据文件\"%s\": %m" + +#: pg_backup_directory.c:446 +#, c-format +msgid "could not open large object TOC file \"%s\" for input: %m" +msgstr "无法为输入: %2$m打开大对象文件\"%1$s\"" + +#: pg_backup_directory.c:457 +#, c-format +msgid "invalid line in large object TOC file \"%s\": \"%s\"" +msgstr "无效行存在于大对象文件\"%s\": \"%s\"" + +#: pg_backup_directory.c:466 +#, c-format +msgid "error reading large object TOC file \"%s\"" +msgstr "在读取大对象文件\"%s\"时发生错误" + +#: pg_backup_directory.c:470 +#, c-format +msgid "could not close large object TOC file \"%s\": %m" +msgstr "无法关闭大对象 TOC 文件\"%s\": %m" + +#: pg_backup_directory.c:689 +#, c-format +msgid "could not write to blobs TOC file" +msgstr "无法写入BLOB到大对象TOC文件" + +#: pg_backup_directory.c:721 +#, c-format +msgid "file name too long: \"%s\"" +msgstr "文件名超长: \"%s\"" + +#: pg_backup_null.c:74 +#, c-format +msgid "this format cannot be read" +msgstr "无法读取这个格式" + +#: pg_backup_tar.c:177 +#, c-format +msgid "could not open TOC file \"%s\" for output: %m" +msgstr "无法为输出打开TOC文件\"%s\": %m" + +#: pg_backup_tar.c:184 +#, c-format +msgid "could not open TOC file for output: %m" +msgstr "无法为输出打开 TOC 文件: %m" + +#: pg_backup_tar.c:203 pg_backup_tar.c:352 +#, c-format +msgid "compression is not supported by tar archive format" +msgstr "不支持tar归档格式的压缩" + +#: pg_backup_tar.c:211 +#, c-format +msgid "could not open TOC file \"%s\" for input: %m" +msgstr "无法为输入打开TOC文件\"%s\": %m" + +#: pg_backup_tar.c:218 +#, c-format +msgid "could not open TOC file for input: %m" +msgstr "无法为输入打开 TOC 文件: %m" + +#: pg_backup_tar.c:338 +#, c-format +msgid "could not find file \"%s\" in archive" +msgstr "无法在归档中找到文件\"%s\"" + +#: pg_backup_tar.c:404 +#, c-format +msgid "could not generate temporary file name: %m" +msgstr "无法生成临时文件名: %m" + +#: pg_backup_tar.c:415 +#, c-format +msgid "could not open temporary file" +msgstr "无法打开临时文件" + +#: pg_backup_tar.c:442 +#, c-format +msgid "could not close tar member" +msgstr "无法关闭 tar 成员" + +#: pg_backup_tar.c:685 +#, c-format +msgid "unexpected COPY statement syntax: \"%s\"" +msgstr "意外的COPY语句语法: \"%s\"" + +#: pg_backup_tar.c:952 +#, c-format +msgid "invalid OID for large object (%u)" +msgstr "用于大对象的非法 OID (%u)" + +#: pg_backup_tar.c:1099 +#, c-format +msgid "could not close temporary file: %m" +msgstr "无法关闭临时文件: %m" + +#: pg_backup_tar.c:1108 +#, c-format +msgid "actual file length (%s) does not match expected (%s)" +msgstr "实际文件长度 (%s) 不匹配预期的长度 (%s)" + +#: pg_backup_tar.c:1165 pg_backup_tar.c:1196 +#, c-format +msgid "could not find header for file \"%s\" in tar archive" +msgstr "无法在tar归档中为文件\"%s\"找到标题头" + +#: pg_backup_tar.c:1183 +#, c-format +msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +msgstr "这个归档格式里不支持不按照顺序转储数据: 要求\"%s\" ,但它在归档文件里位于\"%s\"前面." + +#: pg_backup_tar.c:1230 +#, c-format +msgid "incomplete tar header found (%lu byte)" +msgid_plural "incomplete tar header found (%lu bytes)" +msgstr[0] "找到未完成的tar文件头(%lu个字节)" +msgstr[1] "找到未完成的tar文件头(%lu个字节)" + +#: pg_backup_tar.c:1281 +#, c-format +msgid "corrupt tar header found in %s (expected %d, computed %d) file position %s" +msgstr "在文件 %1$s 的位置 %4$s 发现崩溃的 tar 头(预计在 %2$d, 计算出来在 %3$d)" + +#: pg_backup_utils.c:54 +#, c-format +msgid "unrecognized section name: \"%s\"" +msgstr "无法识别的节名称: \"%s\"" + +#: pg_backup_utils.c:55 pg_dump.c:622 pg_dump.c:639 pg_dumpall.c:341 +#: pg_dumpall.c:351 pg_dumpall.c:360 pg_dumpall.c:369 pg_dumpall.c:377 +#: pg_dumpall.c:391 pg_dumpall.c:469 pg_restore.c:284 pg_restore.c:300 +#: pg_restore.c:318 +#, c-format +msgid "Try \"%s --help\" for more information.\n" +msgstr "请用 \"%s --help\" 获取更多的信息.\n" + +#: pg_backup_utils.c:68 +#, c-format +msgid "out of on_exit_nicely slots" +msgstr "超出on_exit_nicely槽" + +#: pg_dump.c:548 +#, c-format +msgid "compression level must be in range 0..9" +msgstr "压缩级别必须位于0..9的范围内" + +#: pg_dump.c:586 +#, c-format +msgid "extra_float_digits must be in range -15..3" +msgstr "extra_float_digits必须在-15到3之间" + +#: pg_dump.c:609 +#, c-format +msgid "rows-per-insert must be in range %d..%d" +msgstr "rows-per-insert必须位于%d..%d的范围内" + +#: pg_dump.c:637 pg_dumpall.c:349 pg_restore.c:298 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "命令行参数太多 (第一个是 \"%s\")" + +#: pg_dump.c:658 pg_restore.c:327 +#, c-format +msgid "options -s/--schema-only and -a/--data-only cannot be used together" +msgstr "选项 -s/--schema-only和-a/--data-only 不能同时使用" + +#: pg_dump.c:663 +msgid "options -s/--schema-only and --include-foreign-data cannot be used together" +msgstr "选项 -s/--schema-only和--include-foreign-data不能同时使用" + +#: pg_dump.c:666 +#, c-format +msgid "option --include-foreign-data is not supported with parallel backup" +msgstr "并行备份不支持选项--include-foreign-data" + +#: pg_dump.c:670 pg_restore.c:333 +#, c-format +msgid "options -c/--clean and -a/--data-only cannot be used together" +msgstr "选项 -c/--clean和 -a/--data-only不能同时使用" + +#: pg_dump.c:675 pg_dumpall.c:384 pg_restore.c:382 +#, c-format +msgid "option --if-exists requires option -c/--clean" +msgstr "选项 --if-exists 需要选项 -c/ --clean" + +#: pg_dump.c:682 +msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +msgstr "选项---on-conflict-do-nothing需要选项--inserts, --rows-per-insert 或者 --column-inserts" + +#: pg_dump.c:704 +#, c-format +msgid "requested compression not available in this installation -- archive will be uncompressed" +msgstr "所要求的压缩无法在本次安装中获取 -- 归档将不被压缩" + +#: pg_dump.c:725 pg_restore.c:349 +#, c-format +msgid "invalid number of parallel jobs" +msgstr "无效的并行工作数" + +#: pg_dump.c:729 +#, c-format +msgid "parallel backup only supported by the directory format" +msgstr "并行备份只被目录格式支持" + +#: pg_dump.c:784 +#, c-format +msgid "" +"Synchronized snapshots are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"当前服务器版本不支持同步快照.\n" +"如果不需要同步快照功能,\n" +"可以带参数 --no-synchronized-snapshots运行" + +#: pg_dump.c:790 +#, c-format +msgid "Exported snapshots are not supported by this server version." +msgstr "在这个版本的服务器中不支持导出的快照." + +#: pg_dump.c:802 +#, c-format +msgid "last built-in OID is %u" +msgstr "最后的内置 OID 是 %u" + +#: pg_dump.c:811 +#, c-format +msgid "no matching schemas were found" +msgstr "没有找到符合的模式" + +#: pg_dump.c:825 +#, c-format +msgid "no matching tables were found" +msgstr "没有找到符合的表" + +#: pg_dump.c:847 +msgid "no matching extensions were found" +msgstr "没有找到符合的扩展名" + +#: pg_dump.c:1017 +#, c-format +msgid "" +"%s dumps a database as a text file or to other formats.\n" +"\n" +msgstr "" +"%s 把一个数据库转储为纯文本文件或者是其它格式.\n" +"\n" + +#: pg_dump.c:1018 pg_dumpall.c:622 pg_restore.c:462 +#, c-format +msgid "Usage:\n" +msgstr "使用方法:\n" + +#: pg_dump.c:1019 +#, c-format +msgid " %s [OPTION]... [DBNAME]\n" +msgstr " %s [选项]... [数据库名字]\n" + +#: pg_dump.c:1021 pg_dumpall.c:625 pg_restore.c:465 +#, c-format +msgid "" +"\n" +"General options:\n" +msgstr "" +"\n" +"一般选项:\n" + +#: pg_dump.c:1022 +#, c-format +msgid " -f, --file=FILENAME output file or directory name\n" +msgstr " -f, --file=FILENAME 输出文件或目录名\n" + +#: pg_dump.c:1023 +#, c-format +msgid "" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" +" plain text (default))\n" +msgstr "" +" -F, --format=c|d|t|p 输出文件格式 (定制, 目录, tar\n" +" 明文 (默认值))\n" + +#: pg_dump.c:1025 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" +msgstr " -j, --jobs=NUM 执行多个并行任务进行备份转储工作\n" + +#: pg_dump.c:1026 pg_dumpall.c:627 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 详细模式\n" + +#: pg_dump.c:1027 pg_dumpall.c:628 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 输出版本信息, 然后退出\n" + +#: pg_dump.c:1028 +#, c-format +msgid " -Z, --compress=0-9 compression level for compressed formats\n" +msgstr " -Z, --compress=0-9 被压缩格式的压缩级别\n" + +#: pg_dump.c:1029 pg_dumpall.c:629 +#, c-format +msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +msgstr " --lock-wait-timeout=TIMEOUT 在等待表锁超时后操作失败\n" + +#: pg_dump.c:1030 pg_dumpall.c:656 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr " --no-sync 不用等待变化安全写入磁盘\n" + +#: pg_dump.c:1031 pg_dumpall.c:630 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 显示此帮助, 然后退出\n" + +#: pg_dump.c:1033 pg_dumpall.c:631 +#, c-format +msgid "" +"\n" +"Options controlling the output content:\n" +msgstr "" +"\n" +"控制输出内容选项:\n" + +#: pg_dump.c:1034 pg_dumpall.c:632 +#, c-format +msgid " -a, --data-only dump only the data, not the schema\n" +msgstr " -a, --data-only 只转储数据,不包括模式\n" + +#: pg_dump.c:1035 +#, c-format +msgid " -b, --blobs include large objects in dump\n" +msgstr " -b, --blobs 在转储中包括大对象\n" + +#: pg_dump.c:1036 +#, c-format +msgid " -B, --no-blobs exclude large objects in dump\n" +msgstr " -B, --no-blobs 排除转储中的大型对象\n" + +#: pg_dump.c:1037 pg_restore.c:476 +#, c-format +msgid " -c, --clean clean (drop) database objects before recreating\n" +msgstr " -c, --clean 在重新创建之前,先清除(删除)数据库对象\n" + +#: pg_dump.c:1038 +#, c-format +msgid " -C, --create include commands to create database in dump\n" +msgstr " -C, --create 在转储中包括命令,以便创建数据库\n" + +#: pg_dump.c:1039 +msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" +msgstr " -e, --extension=PATTERN 仅转储指定的扩展名\n" + +#: pg_dump.c:1040 pg_dumpall.c:634 +#, c-format +msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +msgstr " -E, --encoding=ENCODING 转储以ENCODING形式编码的数据\n" + +#: pg_dump.c:1041 +msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" +msgstr " -n, --schema=PATTERN 只转储指定的模式\n" + +#: pg_dump.c:1042 +msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +msgstr " -N, --exclude-schema=PATTERN 不转储指定的模式\n" + +#: pg_dump.c:1043 +#, c-format +msgid "" +" -O, --no-owner skip restoration of object ownership in\n" +" plain-text format\n" +msgstr " -O, --no-owner 在明文格式中, 忽略恢复对象所属者\n" + +#: pg_dump.c:1045 pg_dumpall.c:638 +#, c-format +msgid " -s, --schema-only dump only the schema, no data\n" +msgstr " -s, --schema-only 只转储模式, 不包括数据\n" + +#: pg_dump.c:1046 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" +msgstr " -S, --superuser=NAME 在明文格式中使用指定的超级用户名\n" + +#: pg_dump.c:1047 +msgid " -t, --table=PATTERN dump the specified table(s) only\n" +msgstr " -t, --table=PATTERN 只转储指定的表\n" + +#: pg_dump.c:1048 +msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +msgstr " -T, --exclude-table=PATTERN 不转储指定的表\n" + +#: pg_dump.c:1049 pg_dumpall.c:641 +#, c-format +msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" +msgstr " -x, --no-privileges 不要转储权限 (grant/revoke)\n" + +#: pg_dump.c:1050 pg_dumpall.c:642 +#, c-format +msgid " --binary-upgrade for use by upgrade utilities only\n" +msgstr " --binary-upgrade 只能由升级工具使用\n" + +#: pg_dump.c:1051 pg_dumpall.c:643 +#, c-format +msgid " --column-inserts dump data as INSERT commands with column names\n" +msgstr " --column-inserts 以带有列名的INSERT命令形式转储数据\n" + +#: pg_dump.c:1052 pg_dumpall.c:644 +#, c-format +msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +msgstr " --disable-dollar-quoting 取消美元 (符号) 引号, 使用 SQL 标准引号\n" + +#: pg_dump.c:1053 pg_dumpall.c:645 pg_restore.c:493 +#, c-format +msgid " --disable-triggers disable triggers during data-only restore\n" +msgstr " --disable-triggers 在只恢复数据的过程中禁用触发器\n" + +#: pg_dump.c:1054 +#, c-format +msgid "" +" --enable-row-security enable row security (dump only content user has\n" +" access to)\n" +msgstr " --enable-row-security 启用行安全性(只转储用户能够访问的内容)\n" + +#: pg_dump.c:1056 +msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +msgstr " --exclude-table-data=PATTERN 不转储指定的表中的数据\n" + +#: pg_dump.c:1057 pg_dumpall.c:647 +#, c-format +msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" +msgstr " --extra-float-digits=NUM 覆盖extra_float_digits的默认设置\n" + +#: pg_dump.c:1058 pg_dumpall.c:648 pg_restore.c:495 +#, c-format +msgid " --if-exists use IF EXISTS when dropping objects\n" +msgstr " --if-exists 当删除对象时使用IF EXISTS\n" + +#: pg_dump.c:1059 +#, c-format +msgid "" +" --include-foreign-data=PATTERN\n" +" include data of foreign tables on foreign\n" +" servers matching PATTERN\n" +msgstr "" +" --include-foreign-data=PATTERN\n" +" 包含外部服务器上与模式匹配的\n" +" 外部表的数据\n" + +#: pg_dump.c:1062 pg_dumpall.c:649 +#, c-format +msgid " --inserts dump data as INSERT commands, rather than COPY\n" +msgstr " --inserts 以INSERT命令,而不是COPY命令的形式转储数据\n" + +#: pg_dump.c:1063 pg_dumpall.c:650 +#, c-format +msgid " --load-via-partition-root load partitions via the root table\n" +msgstr " --load-via-partition-root 通过根表加载分区\n" + +#: pg_dump.c:1064 pg_dumpall.c:651 +#, c-format +msgid " --no-comments do not dump comments\n" +msgstr " --no-comments 不转储注释\n" + +#: pg_dump.c:1065 pg_dumpall.c:652 +#, c-format +msgid " --no-publications do not dump publications\n" +msgstr " --no-publications 不转储发布\n" + +#: pg_dump.c:1066 pg_dumpall.c:654 +#, c-format +msgid " --no-security-labels do not dump security label assignments\n" +msgstr " --no-security-labels 不转储安全标签的分配\n" + +#: pg_dump.c:1067 pg_dumpall.c:655 +#, c-format +msgid " --no-subscriptions do not dump subscriptions\n" +msgstr " --no-subscriptions 不转储订阅\n" + +#: pg_dump.c:1068 +#, c-format +msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +msgstr " --no-synchronized-snapshots 在并行工作集中不使用同步快照\n" + +#: pg_dump.c:1069 pg_dumpall.c:657 +#, c-format +msgid " --no-tablespaces do not dump tablespace assignments\n" +msgstr " --no-tablespaces 不转储表空间分配信息\n" + +#: pg_dump.c:1070 pg_dumpall.c:658 +msgid " --no-toast-compression do not dump TOAST compression methods\n" +msgstr " --no-toast-compression 不转储TOAST压缩方法\n" + +#: pg_dump.c:1071 pg_dumpall.c:659 +#, c-format +msgid " --no-unlogged-table-data do not dump unlogged table data\n" +msgstr " --no-unlogged-table-data 不转储没有日志的表数据\n" + +#: pg_dump.c:1072 pg_dumpall.c:660 +#, c-format +msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +msgstr " --on-conflict-do-nothing 将ON CONFLICT DO NOTHING添加到INSERT命令\n" + +#: pg_dump.c:1073 pg_dumpall.c:661 +#, c-format +msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" +msgstr " --quote-all-identifiers 所有标识符加引号,即使不是关键字\n" + +#: pg_dump.c:1074 pg_dumpall.c:662 +#, c-format +msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +msgstr " --rows-per-insert=NROWS 每个插入的行数;意味着--inserts\n" + +#: pg_dump.c:1075 +#, c-format +msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION 备份命名的节 (数据前, 数据, 及 数据后)\n" + +#: pg_dump.c:1076 +#, c-format +msgid " --serializable-deferrable wait until the dump can run without anomalies\n" +msgstr " --serializable-deferrable 等到备份可以无异常运行\n" + +#: pg_dump.c:1077 +#, c-format +msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" +msgstr " --snapshot=SNAPSHOT 为转储使用给定的快照\n" + +#: pg_dump.c:1078 pg_restore.c:504 +#, c-format +msgid "" +" --strict-names require table and/or schema include patterns to\n" +" match at least one entity each\n" +msgstr " --strict-names 要求每个表和(或)schema包括模式以匹配至少一个实体\n" + +#: pg_dump.c:1080 pg_dumpall.c:663 pg_restore.c:506 +#, c-format +msgid "" +" --use-set-session-authorization\n" +" use SET SESSION AUTHORIZATION commands instead of\n" +" ALTER OWNER commands to set ownership\n" +msgstr "" +" --use-set-session-authorization\n" +" 使用 SESSION AUTHORIZATION 命令代替\n" +" ALTER OWNER 命令来设置所有权\n" + +#: pg_dump.c:1084 pg_dumpall.c:667 pg_restore.c:510 +#, c-format +msgid "" +"\n" +"Connection options:\n" +msgstr "" +"\n" +"联接选项:\n" + +#: pg_dump.c:1085 +#, c-format +msgid " -d, --dbname=DBNAME database to dump\n" +msgstr " -d, --dbname=DBNAME 对数据库 DBNAME备份\n" + +#: pg_dump.c:1086 pg_dumpall.c:669 pg_restore.c:511 +#, c-format +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=主机名 数据库服务器的主机名或套接字目录\n" + +#: pg_dump.c:1087 pg_dumpall.c:671 pg_restore.c:512 +#, c-format +msgid " -p, --port=PORT database server port number\n" +msgstr " -p, --port=端口号 数据库服务器的端口号\n" + +#: pg_dump.c:1088 pg_dumpall.c:672 pg_restore.c:513 +#, c-format +msgid " -U, --username=NAME connect as specified database user\n" +msgstr " -U, --username=名字 以指定的数据库用户联接\n" + +#: pg_dump.c:1089 pg_dumpall.c:673 pg_restore.c:514 +#, c-format +msgid " -w, --no-password never prompt for password\n" +msgstr " -w, --no-password 永远不提示输入口令\n" + +#: pg_dump.c:1090 pg_dumpall.c:674 pg_restore.c:515 +#, c-format +msgid " -W, --password force password prompt (should happen automatically)\n" +msgstr " -W, --password 强制口令提示 (自动)\n" + +#: pg_dump.c:1091 pg_dumpall.c:675 +#, c-format +msgid " --role=ROLENAME do SET ROLE before dump\n" +msgstr " --role=ROLENAME 在转储前运行SET ROLE\n" + +#: pg_dump.c:1093 +#, c-format +msgid "" +"\n" +"If no database name is supplied, then the PGDATABASE environment\n" +"variable value is used.\n" +"\n" +msgstr "" +"\n" +"如果没有提供数据库名字, 那么使用 PGDATABASE 环境变量\n" +"的数值.\n" +"\n" + +#: pg_dump.c:1095 pg_dumpall.c:679 pg_restore.c:522 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "臭虫报告至<%s>.\n" + +#: pg_dump.c:1096 pg_dumpall.c:680 pg_restore.c:523 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s 主页: <%s>\n" + +#: pg_dump.c:1115 pg_dumpall.c:504 +#, c-format +msgid "invalid client encoding \"%s\" specified" +msgstr "声明了无效的输出格式 \"%s\"" + +#: pg_dump.c:1261 +#, c-format +msgid "" +"Synchronized snapshots on standby servers are not supported by this server version.\n" +"Run with --no-synchronized-snapshots instead if you do not need\n" +"synchronized snapshots." +msgstr "" +"当前服务器版本不支持备用服务器上的同步快照.\n" +"如果不需要同步快照功能,\n" +"可以带参数 --no-synchronized-snapshots运行." + +#: pg_dump.c:1330 +#, c-format +msgid "invalid output format \"%s\" specified" +msgstr "声明了非法的输出格式 \"%s\"" + +#: pg_dump.c:1368 +#, c-format +msgid "no matching schemas were found for pattern \"%s\"" +msgstr "没有为\"%s\"模式找到匹配的schemas" + +#: pg_dump.c:1415 +msgid "no matching extensions were found for pattern \"%s\"" +msgstr "没有为\"%s\"模式找到匹配的扩展" + +#: pg_dump.c:1462 +msgid "no matching foreign servers were found for pattern \"%s\"" +msgstr "没有为\"%s\"模式找到匹配的外部服务器" + +#: pg_dump.c:1525 +#, c-format +msgid "no matching tables were found for pattern \"%s\"" +msgstr "没有为\"%s\"模式找到匹配的表" + +#: pg_dump.c:1948 +#, c-format +msgid "dumping contents of table \"%s.%s\"" +msgstr "正在转储表\"%s.%s\"的内容" + +#: pg_dump.c:2055 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +msgstr "转储表 \"%s\" 的内容的 SQL 命令失败: PQendcopy() 失败." + +#: pg_dump.c:2056 pg_dump.c:2066 +#, c-format +msgid "Error message from server: %s" +msgstr "来自服务器的错误信息: %s" + +#: pg_dump.c:2057 pg_dump.c:2067 +#, c-format +msgid "The command was: %s" +msgstr "命令是: %s" + +#: pg_dump.c:2065 +#, c-format +msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." +msgstr "转储表 \"%s\" 的内容失败: PQgetResult() 失败." + +#: pg_dump.c:2825 +#, c-format +msgid "saving database definition" +msgstr "保存数据库定义" + +#: pg_dump.c:3297 +#, c-format +msgid "saving encoding = %s" +msgstr "正在保存encoding = %s" + +#: pg_dump.c:3322 +#, c-format +msgid "saving standard_conforming_strings = %s" +msgstr "正在保存standard_conforming_strings = %s" + +#: pg_dump.c:3361 +#, c-format +msgid "could not parse result of current_schemas()" +msgstr "无法解析current_schemas()的结果" + +#: pg_dump.c:3380 +#, c-format +msgid "saving search_path = %s" +msgstr "正在保存search_path = %s" + +#: pg_dump.c:3420 +#, c-format +msgid "reading large objects" +msgstr "正在读取大对象" + +#: pg_dump.c:3602 +#, c-format +msgid "saving large objects" +msgstr "保存大对象" + +#: pg_dump.c:3648 +#, c-format +msgid "error reading large object %u: %s" +msgstr "在读取大对象时发生错误%u: %s" + +#: pg_dump.c:3700 +#, c-format +msgid "reading row security enabled for table \"%s.%s\"" +msgstr "为表\"%s.%s\"读取行安全性启用状态" + +#: pg_dump.c:3731 +#, c-format +msgid "reading policies for table \"%s.%s\"" +msgstr "为表\"%s.%s\"读取策略" + +#: pg_dump.c:3883 +#, c-format +msgid "unexpected policy command type: %c" +msgstr "意外的策略命令类型:%c" + +#: pg_dump.c:4037 +#, c-format +msgid "owner of publication \"%s\" appears to be invalid" +msgstr "发行 \"%s\" 的所有者非法" + +#: pg_dump.c:4329 +#, c-format +msgid "subscriptions not dumped because current user is not a superuser" +msgstr "订阅未转储,因为当前用户不是超级用户" + +#: pg_dump.c:4400 +#, c-format +msgid "owner of subscription \"%s\" appears to be invalid" +msgstr "函数订阅\"%s\" 的所有者非法" + +#: pg_dump.c:4443 +#, c-format +msgid "could not parse subpublications array" +msgstr "无法解析子发行数组" + +#: pg_dump.c:4801 +#, c-format +msgid "could not find parent extension for %s %s" +msgstr "无法找到父扩展%s %s" + +#: pg_dump.c:4933 +#, c-format +msgid "owner of schema \"%s\" appears to be invalid" +msgstr "模式 \"%s\" 的所有者非法" + +#: pg_dump.c:4956 +#, c-format +msgid "schema with OID %u does not exist" +msgstr "OID 为 %u 的模式不存在" + +#: pg_dump.c:5285 +#, c-format +msgid "owner of data type \"%s\" appears to be invalid" +msgstr "数据类型 \"%s\" 的所有者非法" + +#: pg_dump.c:5369 +#, c-format +msgid "owner of operator \"%s\" appears to be invalid" +msgstr "操作符 \"%s\" 的所有者非法" + +#: pg_dump.c:5668 +#, c-format +msgid "owner of operator class \"%s\" appears to be invalid" +msgstr "操作符表 \"%s\" 无效" + +#: pg_dump.c:5751 +#, c-format +msgid "owner of operator family \"%s\" appears to be invalid" +msgstr "操作符 \"%s\" 的所有者无效" + +#: pg_dump.c:5919 +#, c-format +msgid "owner of aggregate function \"%s\" appears to be invalid" +msgstr "聚集函数 \"%s\" 的所有者非法" + +#: pg_dump.c:6178 +#, c-format +msgid "owner of function \"%s\" appears to be invalid" +msgstr "函数 \"%s\" 的所有者非法" + +#: pg_dump.c:7005 +#, c-format +msgid "owner of table \"%s\" appears to be invalid" +msgstr "数据表 \"%s\" 的所有者非法" + +#: pg_dump.c:7047 pg_dump.c:17485 +#, c-format +msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" +msgstr "健全检查失败,序列OID %2$u 的源表 OID%1$u 未找到" + +#: pg_dump.c:7186 +#, c-format +msgid "reading indexes for table \"%s.%s\"" +msgstr "为表\"%s.%s\"读取索引" + +#: pg_dump.c:7600 +#, c-format +msgid "reading foreign key constraints for table \"%s.%s\"" +msgstr "为表\"%s.%s\"读取外键约束" + +#: pg_dump.c:7879 +#, c-format +msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +msgstr "健全检查失败,pg_rewrite项OID %2$u 的源表 OID%1$u 未找到" + +#: pg_dump.c:7963 +#, c-format +msgid "reading triggers for table \"%s.%s\"" +msgstr "为表\"%s.%s\"读取触发器" + +#: pg_dump.c:8144 +#, c-format +msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +msgstr "对在表 \"%2$s\" 上的外键触发器 \"%1$s\" 上的查询生成了 NULL 个引用表(表的 OID 是: %3$u)" + +#: pg_dump.c:8694 +#, c-format +msgid "finding the columns and types of table \"%s.%s\"" +msgstr "正在查找表\"%s.%s\"的列和类型" + +#: pg_dump.c:8818 +#, c-format +msgid "invalid column numbering in table \"%s\"" +msgstr "在表 \"%s\" 中的字段个数是无效的" + +#: pg_dump.c:8857 +#, c-format +msgid "finding default expressions of table \"%s.%s\"" +msgstr "正在查找表\"%s.%s\"的默认表达式" + +#: pg_dump.c:8879 +#, c-format +msgid "invalid adnum value %d for table \"%s\"" +msgstr "表 \"%2$s\" 的无效 adnum 值 %1$d" + +#: pg_dump.c:8972 +#, c-format +msgid "finding check constraints for table \"%s.%s\"" +msgstr "正在查找表\"%s.%s\"的检查约束" + +#: pg_dump.c:9021 +#, c-format +msgid "expected %d check constraint on table \"%s\" but found %d" +msgid_plural "expected %d check constraints on table \"%s\" but found %d" +msgstr[0] "在表\"%2$s\"上期望有%1$d个检查约束,但是找到了%3$d个" +msgstr[1] "在表\"%2$s\"上期望有%1$d个检查约束,但是找到了%3$d个" + +#: pg_dump.c:9025 +#, c-format +msgid "(The system catalogs might be corrupted.)" +msgstr "(系统表可能损坏了.)" + +#: pg_dump.c:10610 +#, c-format +msgid "typtype of data type \"%s\" appears to be invalid" +msgstr "数据类型 \"%s\" 的所有者看起来无效" + +#: pg_dump.c:11962 +#, c-format +msgid "bogus value in proargmodes array" +msgstr "无法分析 proargmodes 数组" + +#: pg_dump.c:12269 +#, c-format +msgid "could not parse proallargtypes array" +msgstr "无法分析 proallargtypes 数组" + +#: pg_dump.c:12285 +#, c-format +msgid "could not parse proargmodes array" +msgstr "无法分析 proargmodes 数组" + +#: pg_dump.c:12299 +#, c-format +msgid "could not parse proargnames array" +msgstr "无法分析 proargnames 数组" + +#: pg_dump.c:12309 +#, c-format +msgid "could not parse proconfig array" +msgstr "无法解析 proconfig 数组" + +#: pg_dump.c:12389 +#, c-format +msgid "unrecognized provolatile value for function \"%s\"" +msgstr "函数 \"%s\" 的意外正向易失值" + +#: pg_dump.c:12439 pg_dump.c:14390 +#, c-format +msgid "unrecognized proparallel value for function \"%s\"" +msgstr "函数\"%s\"的proparallel值无法识别" + +#: pg_dump.c:12578 pg_dump.c:12687 pg_dump.c:12694 +#, c-format +msgid "could not find function definition for function with OID %u" +msgstr "找不到带有OID %u的函数的函数定义" + +#: pg_dump.c:12617 +#, c-format +msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" +msgstr "在pg_cast.castfunc或者pg_cast.castmethod字段中的是假值" + +#: pg_dump.c:12620 +#, c-format +msgid "bogus value in pg_cast.castmethod field" +msgstr "在pg_cast.castmethod字段中的是假值" + +#: pg_dump.c:12713 +#, c-format +msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +msgstr "臆造的转换定义,至少trffromsql和trftosql之一应该为非零" + +#: pg_dump.c:12730 +#, c-format +msgid "bogus value in pg_transform.trffromsql field" +msgstr "在pg_transform.trffromsql域中的是臆造值" + +#: pg_dump.c:12751 +#, c-format +msgid "bogus value in pg_transform.trftosql field" +msgstr "在pg_transform.trftosql域中的是臆造值" + +#: pg_dump.c:12903 +msgid "postfix operators are not supported anymore (operator \"%s\")" +msgstr "运不再支持后缀运算符(运算符\"%s\")" + +#: pg_dump.c:13073 +#, c-format +msgid "could not find operator with OID %s" +msgstr "未找到 OID 为 %s 的操作符" + +#: pg_dump.c:13141 +#, c-format +msgid "invalid type \"%c\" of access method \"%s\"" +msgstr "访问方法\"%2$s\"的类型\"%1$c\"无效" + +#: pg_dump.c:13895 +#, c-format +msgid "unrecognized collation provider: %s" +msgstr "无法识别的排序规则提供程序: %s" + +#: pg_dump.c:14309 +#, c-format +msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" +msgstr "无法识别的aggfinalmodify聚合值 \"%s\"" + +#: pg_dump.c:14365 +#, c-format +msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" +msgstr "无法识别的aggmfinalmodify聚合值 \"%s\"" + +#: pg_dump.c:15087 +#, c-format +msgid "unrecognized object type in default privileges: %d" +msgstr "缺省权限中存在未知对象类型: %d" + +#: pg_dump.c:15105 +#, c-format +msgid "could not parse default ACL list (%s)" +msgstr "无法解析缺省ACL列表(%s)" + +#: pg_dump.c:15190 +#, c-format +msgid "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "无法为对象\"%3$s\" (%4$s)解析初始GRANT ACL列表 (%1$s) 或者初始REVOKE ACL列表 (%2$s) " + +#: pg_dump.c:15198 +#, c-format +msgid "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +msgstr "无法为对象\"%3$s\" (%4$s)解析GRANT ACL列表 (%1$s) 或者REVOKE ACL列表 (%2$s)" + +#: pg_dump.c:15713 +#, c-format +msgid "query to obtain definition of view \"%s\" returned no data" +msgstr "获取视图 \"%s\" 定义的查询没有返回数据" + +#: pg_dump.c:15716 +#, c-format +msgid "query to obtain definition of view \"%s\" returned more than one definition" +msgstr "获取视图 \"%s\" 定义的查询返回超过一个定义" + +#: pg_dump.c:15723 +#, c-format +msgid "definition of view \"%s\" appears to be empty (length zero)" +msgstr "视图 \"%s\" 的定义是空的(零长)" + +#: pg_dump.c:15807 +#, c-format +msgid "WITH OIDS is not supported anymore (table \"%s\")" +msgstr "不再支持 WITH OIDS (表\"%s\")" + +#: pg_dump.c:16672 +#, c-format +msgid "invalid column number %d for table \"%s\"" +msgstr "对于表 \"%2$s\" 字段个数 %1$d 是无效的" + +#: pg_dump.c:16749 +msgid "could not parse index statistic columns" +msgstr "无法解析索引统计列" + +#: pg_dump.c:16751 +msgid "could not parse index statistic values" +msgstr "无法解析索引统计值" + +#: pg_dump.c:16753 +#, c-format +msgid "mismatched number of columns and values for index statistics" +msgstr "" + +#: pg_dump.c:16970 +#, c-format +msgid "missing index for constraint \"%s\"" +msgstr "对于约束 \"%s\" 缺少索引" + +#: pg_dump.c:17195 +#, c-format +msgid "unrecognized constraint type: %c" +msgstr "未知的约束类型: %c" + +#: pg_dump.c:17327 pg_dump.c:17550 +#, c-format +msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" +msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" +msgstr[0] "查询得到了序列\"%s\"的数据,返回了%d条记录(期望一条)" +msgstr[1] "查询得到了序列\"%s\"的数据,返回了%d条记录(期望一条)" + +#: pg_dump.c:17361 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "无法识别的序列类型: %s" + +#: pg_dump.c:17648 +#, c-format +msgid "unexpected tgtype value: %d" +msgstr "意外的tgtype值: %d" + +#: pg_dump.c:17722 +#, c-format +msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +msgstr "给表 \"%3$s\" 上的触发器 \"%2$s\" 的错误参数 (%1$s)" + +#: pg_dump.c:17991 +#, c-format +msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +msgstr "获取表 \"%2$s\" 的规则 \"%1$s\" 查询失败: 返回了错误的行数" + +#: pg_dump.c:18153 +#, c-format +msgid "could not find referenced extension %u" +msgstr "找不到引用的扩展名%u" + +#: pg_dump.c:18244 +msgid "could not parse extension configuration array" +msgstr "无法解析扩展配置数组" + +#: pg_dump.c:18246 +msgid "could not parse extension condition array" +msgstr "无法解析扩展条件数组" + +#: pg_dump.c:18248 +#, c-format +msgid "mismatched number of configurations and conditions for extension" +msgstr "扩展的配置和条件数量不匹配" + +#: pg_dump.c:18380 +#, c-format +msgid "reading dependency data" +msgstr "读取从属数据" + +#: pg_dump.c:18473 +#, c-format +msgid "no referencing object %u %u" +msgstr "没有引用对象%u %u" + +#: pg_dump.c:18484 +#, c-format +msgid "no referenced object %u %u" +msgstr "没有引用的对象 %u %u" + +#: pg_dump.c:18858 +#, c-format +msgid "could not parse reloptions array" +msgstr "无法解析 reloptions 数组" + +#: pg_dump_sort.c:411 +#, c-format +msgid "invalid dumpId %d" +msgstr "无效的dumpId %d" + +#: pg_dump_sort.c:417 +#, c-format +msgid "invalid dependency %d" +msgstr "无效的依赖 %d" + +#: pg_dump_sort.c:650 +#, c-format +msgid "could not identify dependency loop" +msgstr "无法标识循环依赖" + +#: pg_dump_sort.c:1221 +#, c-format +msgid "there are circular foreign-key constraints on this table:" +msgid_plural "there are circular foreign-key constraints among these tables:" +msgstr[0] "表上存在循环外键约束:" +msgstr[1] "表上存在循环外键约束:" + +#: pg_dump_sort.c:1225 pg_dump_sort.c:1245 +#, c-format +msgid " %s" +msgstr " %s" + +#: pg_dump_sort.c:1226 +#, c-format +msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +msgstr "不使用 --disable-triggers 选项或者临时删除约束,你将不能对备份进行恢复." + +#: pg_dump_sort.c:1227 +#, c-format +msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." +msgstr "考虑使用完全备份代替 --data-only选项进行备份以避免此问题." + +#: pg_dump_sort.c:1239 +#, c-format +msgid "could not resolve dependency loop among these items:" +msgstr "无法解析这些项的循环依赖:" + +#: pg_dumpall.c:202 +#, c-format +msgid "" +"The program \"%s\" is needed by %s but was not found in the\n" +"same directory as \"%s\".\n" +"Check your installation." +msgstr "" +"%2$s需要程序\"%1$s\"\n" +"但在与\"%3$s\"相同的目录中找不到该程序.\n" +"检查您的安装." + +#: pg_dumpall.c:207 +#, c-format +msgid "" +"The program \"%s\" was found by \"%s\"\n" +"but was not the same version as %s.\n" +"Check your installation." +msgstr "" +"程序\"%s\"是由\"%s\"找到的\n" +"但与%s的版本不同.\n" +"检查您的安装." + +#: pg_dumpall.c:359 +msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +msgstr "选项--exclude-database不能与-g/--globals-only、-r/--roles-only或-t/--tablespaces-only一起使用" + +#: pg_dumpall.c:368 +#, c-format +msgid "options -g/--globals-only and -r/--roles-only cannot be used together" +msgstr "选项-g/--globals-only和-r/--roles-only不能同时使用" + +#: pg_dumpall.c:376 +#, c-format +msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" +msgstr "选项 -g/--globals-only和-t/--tablespaces-only不能同时使用" + +#: pg_dumpall.c:390 +#, c-format +msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" +msgstr "选项 -r/--roles-only和 -t/--tablespaces-only不能同时使用" + +#: pg_dumpall.c:453 pg_dumpall.c:1756 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "无法与数据库 \"%s\" 联接" + +#: pg_dumpall.c:467 +#, c-format +msgid "" +"could not connect to databases \"postgres\" or \"template1\"\n" +"Please specify an alternative database." +msgstr "" +"无法连接到数据库 \"postgres\"或\"template1\"\n" +"请指定另外一个数据库." + +#: pg_dumpall.c:621 +#, c-format +msgid "" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"\n" +msgstr "" +"%s 抽取一个 PostgreSQL 数据库簇进一个 SQL 脚本文件.\n" +"\n" + +#: pg_dumpall.c:623 +#, c-format +msgid " %s [OPTION]...\n" +msgstr " %s [选项]...\n" + +#: pg_dumpall.c:626 +#, c-format +msgid " -f, --file=FILENAME output file name\n" +msgstr " -f, --file=FILENAME 输出文件名\n" + +#: pg_dumpall.c:633 +#, c-format +msgid " -c, --clean clean (drop) databases before recreating\n" +msgstr " -c, --clean 在重新创建数据库前先清除(删除)数据库\n" + +#: pg_dumpall.c:635 +#, c-format +msgid " -g, --globals-only dump only global objects, no databases\n" +msgstr " -g, --globals-only 只转储全局对象, 不包括数据库\n" + +#: pg_dumpall.c:636 pg_restore.c:485 +#, c-format +msgid " -O, --no-owner skip restoration of object ownership\n" +msgstr " -O, --no-owner 不恢复对象所属者\n" + +#: pg_dumpall.c:637 +#, c-format +msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" +msgstr " -r, --roles-only 只转储角色,不包括数据库或表空间\n" + +#: pg_dumpall.c:639 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use in the dump\n" +msgstr " -S, --superuser=NAME 在转储中, 指定的超级用户名\n" + +#: pg_dumpall.c:640 +#, c-format +msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +msgstr " -t, --tablespaces-only 只转储表空间,而不转储数据库或角色\n" + +#: pg_dumpall.c:646 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +msgstr " --exclude-database=PATTERN 排除名称与PATTERN匹配的数据库\n" + +#: pg_dumpall.c:653 +#, c-format +msgid " --no-role-passwords do not dump passwords for roles\n" +msgstr " --no-role-passwords 不转储角色的密码\n" + +#: pg_dumpall.c:668 +#, c-format +msgid " -d, --dbname=CONNSTR connect using connection string\n" +msgstr " -d, --dbname=CONNSTR 连接数据库使用的连接串\n" + +#: pg_dumpall.c:670 +#, c-format +msgid " -l, --database=DBNAME alternative default database\n" +msgstr " -l, --database=DBNAME 另一个缺省数据库\n" + +#: pg_dumpall.c:677 +#, c-format +msgid "" +"\n" +"If -f/--file is not used, then the SQL script will be written to the standard\n" +"output.\n" +"\n" +msgstr "" +"\n" +"如果没有使用 -f/--file,那么将把SQL脚本写到标准输出.\n" +"\n" + +#: pg_dumpall.c:883 +#, c-format +msgid "role name starting with \"pg_\" skipped (%s)" +msgstr "以\"pg_\"开始的角色名称已被跳过 (%s)" + +#: pg_dumpall.c:1284 +#, c-format +msgid "could not parse ACL list (%s) for tablespace \"%s\"" +msgstr "无法为表空间 \"%2$s\" 分析 ACL 列表 (%1$s)" + +#: pg_dumpall.c:1501 +msgid "excluding database \"%s\"" +msgstr "正在排除数据库 \"%s\"" + +#: pg_dumpall.c:1505 +msgid "dumping database \"%s\"" +msgstr "正在转储数据库 \"%s\"" + +#: pg_dumpall.c:1537 +#, c-format +msgid "pg_dump failed on database \"%s\", exiting" +msgstr "pg_dump 失败在数据库 \"%s\", 正在退出" + +#: pg_dumpall.c:1546 +#, c-format +msgid "could not re-open the output file \"%s\": %m" +msgstr "无法重新打开输出文件 \"%s\":%m" + +#: pg_dumpall.c:1590 +#, c-format +msgid "running \"%s\"" +msgstr "正在运行 \"%s\"" + +#: pg_dumpall.c:1805 +#, c-format +msgid "could not get server version" +msgstr "无法从服务器获取版本" + +#: pg_dumpall.c:1811 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "无法分析版本字串 \"%s\"" + +#: pg_dumpall.c:1883 pg_dumpall.c:1906 +#, c-format +msgid "executing %s" +msgstr "正在执行: %s" + +#: pg_restore.c:308 +#, c-format +msgid "one of -d/--dbname and -f/--file must be specified" +msgstr "必须指定-d/--dbname和-f/--file之一" + +#: pg_restore.c:317 +#, c-format +msgid "options -d/--dbname and -f/--file cannot be used together" +msgstr "选项 -d/--dbname和-f/--file不能同时使用" + +#: pg_restore.c:343 +#, c-format +msgid "options -C/--create and -1/--single-transaction cannot be used together" +msgstr "选项 -C/--create和 -1/--single-transaction不能同时使用" + +#: pg_restore.c:357 +#, c-format +msgid "maximum number of parallel jobs is %d" +msgstr "已经达到并行工作集的最大数 %d" + +#: pg_restore.c:366 +#, c-format +msgid "cannot specify both --single-transaction and multiple jobs" +msgstr "不能同时指定选项--single-transaction和多个任务" + +#: pg_restore.c:408 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +msgstr "不可识别的归档格式\"%s\"; 请指定 \"c\", \"d\", 或 \"t\"" + +#: pg_restore.c:448 +#, c-format +msgid "errors ignored on restore: %d" +msgstr "恢复中忽略错误: %d" + +#: pg_restore.c:461 +#, c-format +msgid "" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"\n" +msgstr "" +"%s 从一个归档中恢复一个由 pg_dump 创建的 PostgreSQL 数据库.\n" +"\n" + +#: pg_restore.c:463 +#, c-format +msgid " %s [OPTION]... [FILE]\n" +msgstr " %s [选项]... [文件名]\n" + +#: pg_restore.c:466 +#, c-format +msgid " -d, --dbname=NAME connect to database name\n" +msgstr " -d, --dbname=名字 连接数据库名字\n" + +#: pg_restore.c:467 +#, c-format +msgid " -f, --file=FILENAME output file name (- for stdout)\n" +msgstr " -f, --file=文件名 输出文件名(- 对于stdout)\n" + +#: pg_restore.c:468 +#, c-format +msgid " -F, --format=c|d|t backup file format (should be automatic)\n" +msgstr " -F, --format=c|d|t 备份文件格式(应该自动进行)\n" + +#: pg_restore.c:469 +#, c-format +msgid " -l, --list print summarized TOC of the archive\n" +msgstr " -l, --list 打印归档文件的 TOC 概述\n" + +#: pg_restore.c:470 +#, c-format +msgid " -v, --verbose verbose mode\n" +msgstr " -v, --verbose 详细模式\n" + +#: pg_restore.c:471 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 输出版本信息, 然后退出\n" + +#: pg_restore.c:472 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 显示此帮助, 然后退出\n" + +#: pg_restore.c:474 +#, c-format +msgid "" +"\n" +"Options controlling the restore:\n" +msgstr "" +"\n" +"恢复控制选项:\n" + +#: pg_restore.c:475 +#, c-format +msgid " -a, --data-only restore only the data, no schema\n" +msgstr " -a, --data-only 只恢复数据, 不包括模式\n" + +#: pg_restore.c:477 +#, c-format +msgid " -C, --create create the target database\n" +msgstr " -C, --create 创建目标数据库\n" + +#: pg_restore.c:478 +#, c-format +msgid " -e, --exit-on-error exit on error, default is to continue\n" +msgstr " -e, --exit-on-error 发生错误退出, 默认为继续\n" + +#: pg_restore.c:479 +#, c-format +msgid " -I, --index=NAME restore named index\n" +msgstr " -I, --index=NAME 恢复指定名称的索引\n" + +#: pg_restore.c:480 +#, c-format +msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" +msgstr " -j, --jobs=NUM 执行多个并行任务进行恢复工作\n" + +#: pg_restore.c:481 +#, c-format +msgid "" +" -L, --use-list=FILENAME use table of contents from this file for\n" +" selecting/ordering output\n" +msgstr "" +" -L, --use-list=FILENAME 从这个文件中使用指定的内容表排序\n" +" 输出\n" + +#: pg_restore.c:483 +#, c-format +msgid " -n, --schema=NAME restore only objects in this schema\n" +msgstr " -n, --schema=NAME 在这个模式中只恢复对象\n" + +#: pg_restore.c:484 +#, c-format +msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" +msgstr " -N, --exclude-schema=NAME 不恢复此模式中的对象\n" + +#: pg_restore.c:486 +#, c-format +msgid " -P, --function=NAME(args) restore named function\n" +msgstr " -P, --function=NAME(args) 恢复指定名字的函数\n" + +#: pg_restore.c:487 +#, c-format +msgid " -s, --schema-only restore only the schema, no data\n" +msgstr " -s, --schema-only 只恢复模式, 不包括数据\n" + +#: pg_restore.c:488 +#, c-format +msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" +msgstr " -S, --superuser=NAME 使用指定的超级用户来禁用触发器\n" + +#: pg_restore.c:489 +#, c-format +msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" +msgstr " -t, --table=NAME 恢复命名关系(表、视图等)\n" + +#: pg_restore.c:490 +#, c-format +msgid " -T, --trigger=NAME restore named trigger\n" +msgstr " -T, --trigger=NAME 恢复指定名字的触发器\n" + +#: pg_restore.c:491 +#, c-format +msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +msgstr " -x, --no-privileges 跳过处理权限的恢复 (grant/revoke)\n" + +#: pg_restore.c:492 +#, c-format +msgid " -1, --single-transaction restore as a single transaction\n" +msgstr " -1, --single-transaction 作为单个事务恢复\n" + +#: pg_restore.c:494 +#, c-format +msgid " --enable-row-security enable row security\n" +msgstr " --enable-row-security 启用行安全性\n" + +#: pg_restore.c:496 +#, c-format +msgid " --no-comments do not restore comments\n" +msgstr " --no-comments 不恢复注释\n" + +#: pg_restore.c:497 +#, c-format +msgid "" +" --no-data-for-failed-tables do not restore data of tables that could not be\n" +" created\n" +msgstr "" +" --no-data-for-failed-tables 对那些无法创建的表不进行\n" +" 数据恢复\n" + +#: pg_restore.c:499 +#, c-format +msgid " --no-publications do not restore publications\n" +msgstr " --no-publications 不恢复发行\n" + +#: pg_restore.c:500 +#, c-format +msgid " --no-security-labels do not restore security labels\n" +msgstr " --no-security-labels 不恢复安全标签信息\n" + +#: pg_restore.c:501 +#, c-format +msgid " --no-subscriptions do not restore subscriptions\n" +msgstr " --no-subscriptions 不恢复订阅\n" + +#: pg_restore.c:502 +#, c-format +msgid " --no-tablespaces do not restore tablespace assignments\n" +msgstr " --no-tablespaces 不恢复表空间的分配信息\n" + +#: pg_restore.c:503 +#, c-format +msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" +msgstr " --section=SECTION 恢复命名节 (数据前、数据及数据后)\n" + +#: pg_restore.c:516 +#, c-format +msgid " --role=ROLENAME do SET ROLE before restore\n" +msgstr " --role=ROLENAME 在恢复前执行SET ROLE操作\n" + +#: pg_restore.c:518 +#, c-format +msgid "" +"\n" +"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" +"multiple times to select multiple objects.\n" +msgstr "" +"\n" +"选项 -I, -n, -N, -P, -t, -T, 以及 --section 可以组合使用和指定\n" +"多次用于选择多个对象.\n" + +#: pg_restore.c:521 +#, c-format +msgid "" +"\n" +"If no input file name is supplied, then standard input is used.\n" +"\n" +msgstr "" +"\n" +"如果没有提供输入文件名, 则使用标准输入.\n" +"\n" + diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl new file mode 100644 index 0000000..9f12ca6 --- /dev/null +++ b/src/bin/pg_dump/t/001_basic.pl @@ -0,0 +1,190 @@ + +# Copyright (c) 2021, PostgreSQL Global Development Group + +use strict; +use warnings; + +use Config; +use PostgresNode; +use TestLib; +use Test::More tests => 82; + +my $tempdir = TestLib::tempdir; +my $tempdir_short = TestLib::tempdir_short; + +######################################### +# Basic checks + +program_help_ok('pg_dump'); +program_version_ok('pg_dump'); +program_options_handling_ok('pg_dump'); + +program_help_ok('pg_restore'); +program_version_ok('pg_restore'); +program_options_handling_ok('pg_restore'); + +program_help_ok('pg_dumpall'); +program_version_ok('pg_dumpall'); +program_options_handling_ok('pg_dumpall'); + +######################################### +# Test various invalid options and disallowed combinations +# Doesn't require a PG instance to be set up, so do this first. + +command_fails_like( + [ 'pg_dump', 'qqq', 'abc' ], + qr/\Qpg_dump: error: too many command-line arguments (first is "abc")\E/, + 'pg_dump: too many command-line arguments'); + +command_fails_like( + [ 'pg_restore', 'qqq', 'abc' ], + qr/\Qpg_restore: error: too many command-line arguments (first is "abc")\E/, + 'pg_restore: too many command-line arguments'); + +command_fails_like( + [ 'pg_dumpall', 'qqq', 'abc' ], + qr/\Qpg_dumpall: error: too many command-line arguments (first is "qqq")\E/, + 'pg_dumpall: too many command-line arguments'); + +command_fails_like( + [ 'pg_dump', '-s', '-a' ], + qr/\Qpg_dump: error: options -s\/--schema-only and -a\/--data-only cannot be used together\E/, + 'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_dump', '-s', '--include-foreign-data=xxx' ], + qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/, + 'pg_dump: options -s/--schema-only and --include-foreign-data cannot be used together' +); + +command_fails_like( + [ 'pg_dump', '-j2', '--include-foreign-data=xxx' ], + qr/\Qpg_dump: error: option --include-foreign-data is not supported with parallel backup\E/, + 'pg_dump: option --include-foreign-data is not supported with parallel backup' +); + +command_fails_like( + ['pg_restore'], + qr{\Qpg_restore: error: one of -d/--dbname and -f/--file must be specified\E}, + 'pg_restore: error: one of -d/--dbname and -f/--file must be specified'); + +command_fails_like( + [ 'pg_restore', '-s', '-a', '-f -' ], + qr/\Qpg_restore: error: options -s\/--schema-only and -a\/--data-only cannot be used together\E/, + 'pg_restore: options -s/--schema-only and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_restore', '-d', 'xxx', '-f', 'xxx' ], + qr/\Qpg_restore: error: options -d\/--dbname and -f\/--file cannot be used together\E/, + 'pg_restore: options -d/--dbname and -f/--file cannot be used together'); + +command_fails_like( + [ 'pg_dump', '-c', '-a' ], + qr/\Qpg_dump: error: options -c\/--clean and -a\/--data-only cannot be used together\E/, + 'pg_dump: options -c/--clean and -a/--data-only cannot be used together'); + +command_fails_like( + [ 'pg_restore', '-c', '-a', '-f -' ], + qr/\Qpg_restore: error: options -c\/--clean and -a\/--data-only cannot be used together\E/, + 'pg_restore: options -c/--clean and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_dump', '--if-exists' ], + qr/\Qpg_dump: error: option --if-exists requires option -c\/--clean\E/, + 'pg_dump: option --if-exists requires option -c/--clean'); + +command_fails_like( + [ 'pg_dump', '-j3' ], + qr/\Qpg_dump: error: parallel backup only supported by the directory format\E/, + 'pg_dump: parallel backup only supported by the directory format'); + +command_fails_like( + [ 'pg_dump', '-j', '-1' ], + qr/\Qpg_dump: error: invalid number of parallel jobs\E/, + 'pg_dump: invalid number of parallel jobs'); + +command_fails_like( + [ 'pg_dump', '-F', 'garbage' ], + qr/\Qpg_dump: error: invalid output format\E/, + 'pg_dump: invalid output format'); + +command_fails_like( + [ 'pg_restore', '-j', '-1', '-f -' ], + qr/\Qpg_restore: error: invalid number of parallel jobs\E/, + 'pg_restore: invalid number of parallel jobs'); + +command_fails_like( + [ 'pg_restore', '--single-transaction', '-j3', '-f -' ], + qr/\Qpg_restore: error: cannot specify both --single-transaction and multiple jobs\E/, + 'pg_restore: cannot specify both --single-transaction and multiple jobs'); + +command_fails_like( + [ 'pg_dump', '-Z', '-1' ], + qr/\Qpg_dump: error: compression level must be in range 0..9\E/, + 'pg_dump: compression level must be in range 0..9'); + +command_fails_like( + [ 'pg_dump', '--extra-float-digits', '-16' ], + qr/\Qpg_dump: error: extra_float_digits must be in range -15..3\E/, + 'pg_dump: extra_float_digits must be in range -15..3'); + +command_fails_like( + [ 'pg_dump', '--rows-per-insert', '0' ], + qr/\Qpg_dump: error: rows-per-insert must be in range 1..2147483647\E/, + 'pg_dump: rows-per-insert must be in range 1..2147483647'); + +command_fails_like( + [ 'pg_restore', '--if-exists', '-f -' ], + qr/\Qpg_restore: error: option --if-exists requires option -c\/--clean\E/, + 'pg_restore: option --if-exists requires option -c/--clean'); + +command_fails_like( + [ 'pg_restore', '-f -', '-F', 'garbage' ], + qr/\Qpg_restore: error: unrecognized archive format "garbage";\E/, + 'pg_dump: unrecognized archive format'); + +command_fails_like( + [ 'pg_dump', '--on-conflict-do-nothing' ], + qr/pg_dump: error: option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts/, + 'pg_dump: --on-conflict-do-nothing requires --inserts, --rows-per-insert, --column-inserts' +); + +# pg_dumpall command-line argument checks +command_fails_like( + [ 'pg_dumpall', '-g', '-r' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and -r\/--roles-only cannot be used together\E/, + 'pg_dumpall: options -g/--globals-only and -r/--roles-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-g', '-t' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and -t\/--tablespaces-only cannot be used together\E/, + 'pg_dumpall: options -g/--globals-only and -t/--tablespaces-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-r', '-t' ], + qr/\Qpg_dumpall: error: options -r\/--roles-only and -t\/--tablespaces-only cannot be used together\E/, + 'pg_dumpall: options -r/--roles-only and -t/--tablespaces-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '--if-exists' ], + qr/\Qpg_dumpall: error: option --if-exists requires option -c\/--clean\E/, + 'pg_dumpall: option --if-exists requires option -c/--clean'); + +command_fails_like( + [ 'pg_restore', '-C', '-1', '-f -' ], + qr/\Qpg_restore: error: options -C\/--create and -1\/--single-transaction cannot be used together\E/, + 'pg_restore: options -C\/--create and -1\/--single-transaction cannot be used together' +); + +# also fails for -r and -t, but it seems pointless to add more tests for those. +command_fails_like( + [ 'pg_dumpall', '--exclude-database=foo', '--globals-only' ], + qr/\Qpg_dumpall: error: option --exclude-database cannot be used together with -g\/--globals-only\E/, + 'pg_dumpall: option --exclude-database cannot be used together with -g/--globals-only' +); diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl new file mode 100644 index 0000000..7b0ac9c --- /dev/null +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -0,0 +1,3940 @@ + +# Copyright (c) 2021, PostgreSQL Global Development Group + +use strict; +use warnings; + +use Config; +use PostgresNode; +use TestLib; +use Test::More; + +my $tempdir = TestLib::tempdir; +my $tempdir_short = TestLib::tempdir_short; + +############################################################### +# Definition of the pg_dump runs to make. +# +# Each of these runs are named and those names are used below +# to define how each test should (or shouldn't) treat a result +# from a given run. +# +# test_key indicates that a given run should simply use the same +# set of like/unlike tests as another run, and which run that is. +# +# dump_cmd is the pg_dump command to run, which is an array of +# the full command and arguments to run. Note that this is run +# using $node->command_ok(), so the port does not need to be +# specified and is pulled from $PGPORT, which is set by the +# PostgresNode system. +# +# restore_cmd is the pg_restore command to run, if any. Note +# that this should generally be used when the pg_dump goes to +# a non-text file and that the restore can then be used to +# generate a text file to run through the tests from the +# non-text file generated by pg_dump. +# +# TODO: Have pg_restore actually restore to an independent +# database and then pg_dump *that* database (or something along +# those lines) to validate that part of the process. + +my %pgdump_runs = ( + binary_upgrade => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + '--format=custom', + "--file=$tempdir/binary_upgrade.dump", + '-w', + '--schema-only', + '--binary-upgrade', + '-d', 'postgres', # alternative way to specify database + ], + restore_cmd => [ + 'pg_restore', '-Fc', '--verbose', + "--file=$tempdir/binary_upgrade.sql", + "$tempdir/binary_upgrade.dump", + ], + }, + clean => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/clean.sql", + '-c', + '-d', 'postgres', # alternative way to specify database + ], + }, + clean_if_exists => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/clean_if_exists.sql", + '-c', + '--if-exists', + '--encoding=UTF8', # no-op, just tests that option is accepted + 'postgres', + ], + }, + column_inserts => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/column_inserts.sql", '-a', + '--column-inserts', 'postgres', + ], + }, + createdb => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/createdb.sql", + '-C', + '-R', # no-op, just for testing + '-v', + 'postgres', + ], + }, + data_only => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/data_only.sql", + '-a', + '--superuser=test_superuser', + '--disable-triggers', + '-v', # no-op, just make sure it works + 'postgres', + ], + }, + defaults => { + dump_cmd => [ + 'pg_dump', '--no-sync', + '-f', "$tempdir/defaults.sql", + 'postgres', + ], + }, + defaults_no_public => { + database => 'regress_pg_dump_test', + dump_cmd => [ + 'pg_dump', '--no-sync', '-f', "$tempdir/defaults_no_public.sql", + 'regress_pg_dump_test', + ], + }, + defaults_no_public_clean => { + database => 'regress_pg_dump_test', + dump_cmd => [ + 'pg_dump', '--no-sync', '-c', '-f', + "$tempdir/defaults_no_public_clean.sql", + 'regress_pg_dump_test', + ], + }, + + # Do not use --no-sync to give test coverage for data sync. + defaults_custom_format => { + test_key => 'defaults', + dump_cmd => [ + 'pg_dump', '-Fc', '-Z6', + "--file=$tempdir/defaults_custom_format.dump", 'postgres', + ], + restore_cmd => [ + 'pg_restore', '-Fc', + "--file=$tempdir/defaults_custom_format.sql", + "$tempdir/defaults_custom_format.dump", + ], + }, + + # Do not use --no-sync to give test coverage for data sync. + defaults_dir_format => { + test_key => 'defaults', + dump_cmd => [ + 'pg_dump', '-Fd', + "--file=$tempdir/defaults_dir_format", 'postgres', + ], + restore_cmd => [ + 'pg_restore', '-Fd', + "--file=$tempdir/defaults_dir_format.sql", + "$tempdir/defaults_dir_format", + ], + }, + + # Do not use --no-sync to give test coverage for data sync. + defaults_parallel => { + test_key => 'defaults', + dump_cmd => [ + 'pg_dump', '-Fd', '-j2', "--file=$tempdir/defaults_parallel", + 'postgres', + ], + restore_cmd => [ + 'pg_restore', + "--file=$tempdir/defaults_parallel.sql", + "$tempdir/defaults_parallel", + ], + }, + + # Do not use --no-sync to give test coverage for data sync. + defaults_tar_format => { + test_key => 'defaults', + dump_cmd => [ + 'pg_dump', '-Ft', + "--file=$tempdir/defaults_tar_format.tar", 'postgres', + ], + restore_cmd => [ + 'pg_restore', + '--format=tar', + "--file=$tempdir/defaults_tar_format.sql", + "$tempdir/defaults_tar_format.tar", + ], + }, + exclude_dump_test_schema => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/exclude_dump_test_schema.sql", + '--exclude-schema=dump_test', 'postgres', + ], + }, + exclude_test_table => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/exclude_test_table.sql", + '--exclude-table=dump_test.test_table', 'postgres', + ], + }, + exclude_test_table_data => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/exclude_test_table_data.sql", + '--exclude-table-data=dump_test.test_table', + '--no-unlogged-table-data', + 'postgres', + ], + }, + inserts => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/inserts.sql", '-a', + '--inserts', 'postgres', + ], + }, + pg_dumpall_globals => { + dump_cmd => [ + 'pg_dumpall', '-v', "--file=$tempdir/pg_dumpall_globals.sql", + '-g', '--no-sync', + ], + }, + pg_dumpall_globals_clean => { + dump_cmd => [ + 'pg_dumpall', "--file=$tempdir/pg_dumpall_globals_clean.sql", + '-g', '-c', '--no-sync', + ], + }, + pg_dumpall_dbprivs => { + dump_cmd => [ + 'pg_dumpall', '--no-sync', + "--file=$tempdir/pg_dumpall_dbprivs.sql", + ], + }, + pg_dumpall_exclude => { + dump_cmd => [ + 'pg_dumpall', '-v', "--file=$tempdir/pg_dumpall_exclude.sql", + '--exclude-database', '*dump_test*', '--no-sync', + ], + }, + no_toast_compression => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_toast_compression.sql", + '--no-toast-compression', 'postgres', + ], + }, + no_blobs => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_blobs.sql", '-B', + 'postgres', + ], + }, + no_privs => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_privs.sql", '-x', + 'postgres', + ], + }, + no_owner => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_owner.sql", '-O', + 'postgres', + ], + }, + only_dump_test_schema => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/only_dump_test_schema.sql", + '--schema=dump_test', 'postgres', + ], + }, + only_dump_test_table => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/only_dump_test_table.sql", + '--table=dump_test.test_table', + '--lock-wait-timeout=' + . (1000 * $TestLib::timeout_default), + 'postgres', + ], + }, + role => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/role.sql", + '--role=regress_dump_test_role', + '--schema=dump_test_second_schema', + 'postgres', + ], + }, + role_parallel => { + test_key => 'role', + dump_cmd => [ + 'pg_dump', + '--no-sync', + '--format=directory', + '--jobs=2', + "--file=$tempdir/role_parallel", + '--role=regress_dump_test_role', + '--schema=dump_test_second_schema', + 'postgres', + ], + restore_cmd => [ + 'pg_restore', "--file=$tempdir/role_parallel.sql", + "$tempdir/role_parallel", + ], + }, + rows_per_insert => { + dump_cmd => [ + 'pg_dump', + '--no-sync', + "--file=$tempdir/rows_per_insert.sql", + '-a', + '--rows-per-insert=4', + '--table=dump_test.test_table', + '--table=dump_test.test_fourth_table', + 'postgres', + ], + }, + schema_only => { + dump_cmd => [ + 'pg_dump', '--format=plain', + "--file=$tempdir/schema_only.sql", '--no-sync', + '-s', 'postgres', + ], + }, + section_pre_data => { + dump_cmd => [ + 'pg_dump', "--file=$tempdir/section_pre_data.sql", + '--section=pre-data', '--no-sync', + 'postgres', + ], + }, + section_data => { + dump_cmd => [ + 'pg_dump', "--file=$tempdir/section_data.sql", + '--section=data', '--no-sync', + 'postgres', + ], + }, + section_post_data => { + dump_cmd => [ + 'pg_dump', "--file=$tempdir/section_post_data.sql", + '--section=post-data', '--no-sync', 'postgres', + ], + }, + test_schema_plus_blobs => { + dump_cmd => [ + 'pg_dump', "--file=$tempdir/test_schema_plus_blobs.sql", + + '--schema=dump_test', '-b', '-B', '--no-sync', 'postgres', + ], + },); + +############################################################### +# Definition of the tests to run. +# +# Each test is defined using the log message that will be used. +# +# A regexp should be defined for each test which provides the +# basis for the test. That regexp will be run against the output +# file of each of the runs which the test is to be run against +# and the success of the result will depend on if the regexp +# result matches the expected 'like' or 'unlike' case. +# +# The runs listed as 'like' will be checked if they match the +# regexp and, if so, the test passes. All runs which are not +# listed as 'like' will be checked to ensure they don't match +# the regexp; if they do, the test will fail. +# +# The below hashes provide convenience sets of runs. Individual +# runs can be excluded from a general hash by placing that run +# into the 'unlike' section. +# +# For example, there is an 'exclude_test_table' run which runs a +# full pg_dump but with an exclude flag to not include the test +# table. The CREATE TABLE test which creates the test table is +# defined with %full_runs but then has 'exclude_test_table' in +# its 'unlike' list, excluding that test. +# +# There can then be a 'create_sql' and 'create_order' for a +# given test. The 'create_sql' commands are collected up in +# 'create_order' and then run against the database prior to any +# of the pg_dump runs happening. This is what "seeds" the +# system with objects to be dumped out. +# +# There can be a flag called 'lz4', which can be set if the test +# case depends on LZ4. Tests marked with this flag are skipped if +# the build used does not support LZ4. +# +# Building of this hash takes a bit of time as all of the regexps +# included in it are compiled. This greatly improves performance +# as the regexps are used for each run the test applies to. + +# Tests which target the 'dump_test' schema, specifically. +my %dump_test_schema_runs = ( + only_dump_test_schema => 1, + test_schema_plus_blobs => 1,); + +# Tests which are considered 'full' dumps by pg_dump, but there +# are flags used to exclude specific items (ACLs, blobs, etc). +my %full_runs = ( + binary_upgrade => 1, + clean => 1, + clean_if_exists => 1, + createdb => 1, + defaults => 1, + exclude_dump_test_schema => 1, + exclude_test_table => 1, + exclude_test_table_data => 1, + no_toast_compression => 1, + no_blobs => 1, + no_owner => 1, + no_privs => 1, + pg_dumpall_dbprivs => 1, + pg_dumpall_exclude => 1, + schema_only => 1,); + +# This is where the actual tests are defined. +my %tests = ( + 'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role GRANT' => { + create_order => 14, + create_sql => 'ALTER DEFAULT PRIVILEGES + FOR ROLE regress_dump_test_role IN SCHEMA dump_test + GRANT SELECT ON TABLES TO regress_dump_test_role;', + regexp => qr/^ + \QALTER DEFAULT PRIVILEGES \E + \QFOR ROLE regress_dump_test_role IN SCHEMA dump_test \E + \QGRANT SELECT ON TABLES TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role GRANT EXECUTE ON FUNCTIONS' + => { + create_order => 15, + create_sql => 'ALTER DEFAULT PRIVILEGES + FOR ROLE regress_dump_test_role IN SCHEMA dump_test + GRANT EXECUTE ON FUNCTIONS TO regress_dump_test_role;', + regexp => qr/^ + \QALTER DEFAULT PRIVILEGES \E + \QFOR ROLE regress_dump_test_role IN SCHEMA dump_test \E + \QGRANT ALL ON FUNCTIONS TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role REVOKE' => { + create_order => 55, + create_sql => 'ALTER DEFAULT PRIVILEGES + FOR ROLE regress_dump_test_role + REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;', + regexp => qr/^ + \QALTER DEFAULT PRIVILEGES \E + \QFOR ROLE regress_dump_test_role \E + \QREVOKE ALL ON FUNCTIONS FROM PUBLIC;\E + /xm, + like => { %full_runs, section_post_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'ALTER DEFAULT PRIVILEGES FOR ROLE regress_dump_test_role REVOKE SELECT' + => { + create_order => 56, + create_sql => 'ALTER DEFAULT PRIVILEGES + FOR ROLE regress_dump_test_role + REVOKE SELECT ON TABLES FROM regress_dump_test_role;', + regexp => qr/^ + \QALTER DEFAULT PRIVILEGES \E + \QFOR ROLE regress_dump_test_role \E + \QREVOKE ALL ON TABLES FROM regress_dump_test_role;\E\n + \QALTER DEFAULT PRIVILEGES \E + \QFOR ROLE regress_dump_test_role \E + \QGRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLES TO regress_dump_test_role;\E + /xm, + like => { %full_runs, section_post_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'ALTER ROLE regress_dump_test_role' => { + regexp => qr/^ + \QALTER ROLE regress_dump_test_role WITH \E + \QNOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN \E + \QNOREPLICATION NOBYPASSRLS;\E + /xm, + like => { + pg_dumpall_dbprivs => 1, + pg_dumpall_globals => 1, + pg_dumpall_globals_clean => 1, + pg_dumpall_exclude => 1, + }, + }, + + 'ALTER COLLATION test0 OWNER TO' => { + regexp => qr/^\QALTER COLLATION public.test0 OWNER TO \E.+;/m, + collation => 1, + like => { %full_runs, section_pre_data => 1, }, + unlike => { %dump_test_schema_runs, no_owner => 1, }, + }, + + 'ALTER FOREIGN DATA WRAPPER dummy OWNER TO' => { + regexp => qr/^ALTER FOREIGN DATA WRAPPER dummy OWNER TO .+;/m, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_owner => 1, }, + }, + + 'ALTER SERVER s1 OWNER TO' => { + regexp => qr/^ALTER SERVER s1 OWNER TO .+;/m, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_owner => 1, }, + }, + + 'ALTER FUNCTION dump_test.pltestlang_call_handler() OWNER TO' => { + regexp => qr/^ + \QALTER FUNCTION dump_test.pltestlang_call_handler() \E + \QOWNER TO \E + .+;/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER OPERATOR FAMILY dump_test.op_family OWNER TO' => { + regexp => qr/^ + \QALTER OPERATOR FAMILY dump_test.op_family USING btree \E + \QOWNER TO \E + .+;/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER OPERATOR FAMILY dump_test.op_family USING btree' => { + create_order => 75, + create_sql => + 'ALTER OPERATOR FAMILY dump_test.op_family USING btree ADD + OPERATOR 1 <(bigint,int4), + OPERATOR 2 <=(bigint,int4), + OPERATOR 3 =(bigint,int4), + OPERATOR 4 >=(bigint,int4), + OPERATOR 5 >(bigint,int4), + FUNCTION 1 (int4, int4) btint4cmp(int4,int4), + FUNCTION 2 (int4, int4) btint4sortsupport(internal), + FUNCTION 4 (int4, int4) btequalimage(oid);', + # note: it's correct that btint8sortsupport and bigint btequalimage + # are included here: + regexp => qr/^ + \QALTER OPERATOR FAMILY dump_test.op_family USING btree ADD\E\n\s+ + \QOPERATOR 1 <(bigint,integer) ,\E\n\s+ + \QOPERATOR 2 <=(bigint,integer) ,\E\n\s+ + \QOPERATOR 3 =(bigint,integer) ,\E\n\s+ + \QOPERATOR 4 >=(bigint,integer) ,\E\n\s+ + \QOPERATOR 5 >(bigint,integer) ,\E\n\s+ + \QFUNCTION 1 (integer, integer) btint4cmp(integer,integer) ,\E\n\s+ + \QFUNCTION 2 (bigint, bigint) btint8sortsupport(internal) ,\E\n\s+ + \QFUNCTION 2 (integer, integer) btint4sortsupport(internal) ,\E\n\s+ + \QFUNCTION 4 (bigint, bigint) btequalimage(oid) ,\E\n\s+ + \QFUNCTION 4 (integer, integer) btequalimage(oid);\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'ALTER OPERATOR CLASS dump_test.op_class OWNER TO' => { + regexp => qr/^ + \QALTER OPERATOR CLASS dump_test.op_class USING btree \E + \QOWNER TO \E + .+;/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER PUBLICATION pub1 OWNER TO' => { + regexp => qr/^ALTER PUBLICATION pub1 OWNER TO .+;/m, + like => { %full_runs, section_post_data => 1, }, + unlike => { no_owner => 1, }, + }, + + 'ALTER LARGE OBJECT ... OWNER TO' => { + regexp => qr/^ALTER LARGE OBJECT \d+ OWNER TO .+;/m, + like => { + %full_runs, + column_inserts => 1, + data_only => 1, + inserts => 1, + section_pre_data => 1, + test_schema_plus_blobs => 1, + }, + unlike => { + no_blobs => 1, + no_owner => 1, + schema_only => 1, + }, + }, + + 'ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO' => { + regexp => qr/^ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO .+;/m, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_owner => 1, }, + }, + + 'ALTER SCHEMA dump_test OWNER TO' => { + regexp => qr/^ALTER SCHEMA dump_test OWNER TO .+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER SCHEMA dump_test_second_schema OWNER TO' => { + regexp => qr/^ALTER SCHEMA dump_test_second_schema OWNER TO .+;/m, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + }, + unlike => { no_owner => 1, }, + }, + + 'ALTER SEQUENCE test_table_col1_seq' => { + regexp => qr/^ + \QALTER SEQUENCE dump_test.test_table_col1_seq OWNED BY dump_test.test_table.col1;\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE ONLY test_table ADD CONSTRAINT ... PRIMARY KEY' => { + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table\E \n^\s+ + \QADD CONSTRAINT test_table_pkey PRIMARY KEY (col1);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE (partitioned) ADD CONSTRAINT ... FOREIGN KEY' => { + create_order => 4, + create_sql => 'CREATE TABLE dump_test.test_table_fk ( + col1 int references dump_test.test_table) + PARTITION BY RANGE (col1); + CREATE TABLE dump_test.test_table_fk_1 + PARTITION OF dump_test.test_table_fk + FOR VALUES FROM (0) TO (10);', + regexp => qr/ + \QADD CONSTRAINT test_table_fk_col1_fkey FOREIGN KEY (col1) REFERENCES dump_test.test_table\E + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + }, + }, + + 'ALTER TABLE ONLY test_table ALTER COLUMN col1 SET STATISTICS 90' => { + create_order => 93, + create_sql => + 'ALTER TABLE dump_test.test_table ALTER COLUMN col1 SET STATISTICS 90;', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table ALTER COLUMN col1 SET STATISTICS 90;\E\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE ONLY test_table ALTER COLUMN col2 SET STORAGE' => { + create_order => 94, + create_sql => + 'ALTER TABLE dump_test.test_table ALTER COLUMN col2 SET STORAGE EXTERNAL;', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table ALTER COLUMN col2 SET STORAGE EXTERNAL;\E\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE ONLY test_table ALTER COLUMN col3 SET STORAGE' => { + create_order => 95, + create_sql => + 'ALTER TABLE dump_test.test_table ALTER COLUMN col3 SET STORAGE MAIN;', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table ALTER COLUMN col3 SET STORAGE MAIN;\E\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE ONLY test_table ALTER COLUMN col4 SET n_distinct' => { + create_order => 95, + create_sql => + 'ALTER TABLE dump_test.test_table ALTER COLUMN col4 SET (n_distinct = 10);', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table ALTER COLUMN col4 SET (n_distinct=10);\E\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE ONLY dump_test.measurement ATTACH PARTITION measurement_y2006m2' + => { + regexp => qr/^ + \QALTER TABLE ONLY dump_test.measurement ATTACH PARTITION dump_test_second_schema.measurement_y2006m2 \E + \QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n + /xm, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + binary_upgrade => 1, + }, + }, + + 'ALTER TABLE test_table CLUSTER ON test_table_pkey' => { + create_order => 96, + create_sql => + 'ALTER TABLE dump_test.test_table CLUSTER ON test_table_pkey', + regexp => qr/^ + \QALTER TABLE dump_test.test_table CLUSTER ON test_table_pkey;\E\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE test_table DISABLE TRIGGER ALL' => { + regexp => qr/^ + \QSET SESSION AUTHORIZATION 'test_superuser';\E\n\n + \QALTER TABLE dump_test.test_table DISABLE TRIGGER ALL;\E\n\n + \QCOPY dump_test.test_table (col1, col2, col3, col4) FROM stdin;\E + \n(?:\d\t\\N\t\\N\t\\N\n){9}\\\.\n\n\n + \QALTER TABLE dump_test.test_table ENABLE TRIGGER ALL;\E/xm, + like => { data_only => 1, }, + }, + + 'ALTER FOREIGN TABLE foreign_table ALTER COLUMN c1 OPTIONS' => { + regexp => qr/^ + \QALTER FOREIGN TABLE dump_test.foreign_table ALTER COLUMN c1 OPTIONS (\E\n + \s+\Qcolumn_name 'col1'\E\n + \Q);\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'ALTER TABLE test_table OWNER TO' => { + regexp => qr/^\QALTER TABLE dump_test.test_table OWNER TO \E.+;/m, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + no_owner => 1, + }, + }, + + 'ALTER TABLE test_table ENABLE ROW LEVEL SECURITY' => { + create_order => 23, + create_sql => 'ALTER TABLE dump_test.test_table + ENABLE ROW LEVEL SECURITY;', + regexp => + qr/^\QALTER TABLE dump_test.test_table ENABLE ROW LEVEL SECURITY;\E/m, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER TABLE test_second_table OWNER TO' => { + regexp => + qr/^\QALTER TABLE dump_test.test_second_table OWNER TO \E.+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER TABLE measurement OWNER TO' => { + regexp => qr/^\QALTER TABLE dump_test.measurement OWNER TO \E.+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER TABLE measurement_y2006m2 OWNER TO' => { + regexp => + qr/^\QALTER TABLE dump_test_second_schema.measurement_y2006m2 OWNER TO \E.+;/m, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + }, + unlike => { no_owner => 1, }, + }, + + 'ALTER FOREIGN TABLE foreign_table OWNER TO' => { + regexp => + qr/^\QALTER FOREIGN TABLE dump_test.foreign_table OWNER TO \E.+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER TEXT SEARCH CONFIGURATION alt_ts_conf1 OWNER TO' => { + regexp => + qr/^\QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 OWNER TO \E.+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_owner => 1, + }, + }, + + 'ALTER TEXT SEARCH DICTIONARY alt_ts_dict1 OWNER TO' => { + regexp => + qr/^\QALTER TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 OWNER TO \E.+;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_test_table => 1, + no_owner => 1, + role => 1, + }, + }, + + 'BLOB create (using lo_from_bytea)' => { + create_order => 50, + create_sql => + 'SELECT pg_catalog.lo_from_bytea(0, \'\\x310a320a330a340a350a360a370a380a390a\');', + regexp => qr/^SELECT pg_catalog\.lo_create\('\d+'\);/m, + like => { + %full_runs, + column_inserts => 1, + data_only => 1, + inserts => 1, + section_pre_data => 1, + test_schema_plus_blobs => 1, + }, + unlike => { + schema_only => 1, + no_blobs => 1, + }, + }, + + 'BLOB load (using lo_from_bytea)' => { + regexp => qr/^ + \QSELECT pg_catalog.lo_open\E \('\d+',\ \d+\);\n + \QSELECT pg_catalog.lowrite(0, \E + \Q'\x310a320a330a340a350a360a370a380a390a');\E\n + \QSELECT pg_catalog.lo_close(0);\E + /xm, + like => { + %full_runs, + column_inserts => 1, + data_only => 1, + inserts => 1, + section_data => 1, + test_schema_plus_blobs => 1, + }, + unlike => { + binary_upgrade => 1, + no_blobs => 1, + schema_only => 1, + }, + }, + + 'COMMENT ON DATABASE postgres' => { + regexp => qr/^COMMENT ON DATABASE postgres IS .+;/m, + + # Should appear in the same tests as "CREATE DATABASE postgres" + like => { createdb => 1, }, + }, + + 'COMMENT ON EXTENSION plpgsql' => { + regexp => qr/^COMMENT ON EXTENSION plpgsql IS .+;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'COMMENT ON TABLE dump_test.test_table' => { + create_order => 36, + create_sql => 'COMMENT ON TABLE dump_test.test_table + IS \'comment on table\';', + regexp => + qr/^\QCOMMENT ON TABLE dump_test.test_table IS 'comment on table';\E/m, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'COMMENT ON COLUMN dump_test.test_table.col1' => { + create_order => 36, + create_sql => 'COMMENT ON COLUMN dump_test.test_table.col1 + IS \'comment on column\';', + regexp => qr/^ + \QCOMMENT ON COLUMN dump_test.test_table.col1 IS 'comment on column';\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'COMMENT ON COLUMN dump_test.composite.f1' => { + create_order => 44, + create_sql => 'COMMENT ON COLUMN dump_test.composite.f1 + IS \'comment on column of type\';', + regexp => qr/^ + \QCOMMENT ON COLUMN dump_test.composite.f1 IS 'comment on column of type';\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON COLUMN dump_test.test_second_table.col1' => { + create_order => 63, + create_sql => 'COMMENT ON COLUMN dump_test.test_second_table.col1 + IS \'comment on column col1\';', + regexp => qr/^ + \QCOMMENT ON COLUMN dump_test.test_second_table.col1 IS 'comment on column col1';\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON COLUMN dump_test.test_second_table.col2' => { + create_order => 64, + create_sql => 'COMMENT ON COLUMN dump_test.test_second_table.col2 + IS \'comment on column col2\';', + regexp => qr/^ + \QCOMMENT ON COLUMN dump_test.test_second_table.col2 IS 'comment on column col2';\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON CONVERSION dump_test.test_conversion' => { + create_order => 79, + create_sql => 'COMMENT ON CONVERSION dump_test.test_conversion + IS \'comment on test conversion\';', + regexp => + qr/^\QCOMMENT ON CONVERSION dump_test.test_conversion IS 'comment on test conversion';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON COLLATION test0' => { + create_order => 77, + create_sql => 'COMMENT ON COLLATION test0 + IS \'comment on test0 collation\';', + regexp => + qr/^\QCOMMENT ON COLLATION public.test0 IS 'comment on test0 collation';\E/m, + collation => 1, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'COMMENT ON LARGE OBJECT ...' => { + create_order => 65, + create_sql => 'DO $$ + DECLARE myoid oid; + BEGIN + SELECT loid FROM pg_largeobject INTO myoid; + EXECUTE \'COMMENT ON LARGE OBJECT \' || myoid || \' IS \'\'comment on large object\'\';\'; + END; + $$;', + regexp => qr/^ + \QCOMMENT ON LARGE OBJECT \E[0-9]+\Q IS 'comment on large object';\E + /xm, + like => { + %full_runs, + column_inserts => 1, + data_only => 1, + inserts => 1, + section_pre_data => 1, + test_schema_plus_blobs => 1, + }, + unlike => { + no_blobs => 1, + schema_only => 1, + }, + }, + + 'COMMENT ON PUBLICATION pub1' => { + create_order => 55, + create_sql => 'COMMENT ON PUBLICATION pub1 + IS \'comment on publication\';', + regexp => + qr/^COMMENT ON PUBLICATION pub1 IS 'comment on publication';/m, + like => { %full_runs, section_post_data => 1, }, + }, + + 'COMMENT ON SUBSCRIPTION sub1' => { + create_order => 55, + create_sql => 'COMMENT ON SUBSCRIPTION sub1 + IS \'comment on subscription\';', + regexp => + qr/^COMMENT ON SUBSCRIPTION sub1 IS 'comment on subscription';/m, + like => { %full_runs, section_post_data => 1, }, + }, + + 'COMMENT ON TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1' => { + create_order => 84, + create_sql => + 'COMMENT ON TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 + IS \'comment on text search configuration\';', + regexp => + qr/^\QCOMMENT ON TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 IS 'comment on text search configuration';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1' => { + create_order => 84, + create_sql => + 'COMMENT ON TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 + IS \'comment on text search dictionary\';', + regexp => + qr/^\QCOMMENT ON TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 IS 'comment on text search dictionary';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TEXT SEARCH PARSER dump_test.alt_ts_prs1' => { + create_order => 84, + create_sql => 'COMMENT ON TEXT SEARCH PARSER dump_test.alt_ts_prs1 + IS \'comment on text search parser\';', + regexp => + qr/^\QCOMMENT ON TEXT SEARCH PARSER dump_test.alt_ts_prs1 IS 'comment on text search parser';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1' => { + create_order => 84, + create_sql => 'COMMENT ON TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1 + IS \'comment on text search template\';', + regexp => + qr/^\QCOMMENT ON TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1 IS 'comment on text search template';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TYPE dump_test.planets - ENUM' => { + create_order => 68, + create_sql => 'COMMENT ON TYPE dump_test.planets + IS \'comment on enum type\';', + regexp => + qr/^\QCOMMENT ON TYPE dump_test.planets IS 'comment on enum type';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TYPE dump_test.textrange - RANGE' => { + create_order => 69, + create_sql => 'COMMENT ON TYPE dump_test.textrange + IS \'comment on range type\';', + regexp => + qr/^\QCOMMENT ON TYPE dump_test.textrange IS 'comment on range type';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TYPE dump_test.int42 - Regular' => { + create_order => 70, + create_sql => 'COMMENT ON TYPE dump_test.int42 + IS \'comment on regular type\';', + regexp => + qr/^\QCOMMENT ON TYPE dump_test.int42 IS 'comment on regular type';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COMMENT ON TYPE dump_test.undefined - Undefined' => { + create_order => 71, + create_sql => 'COMMENT ON TYPE dump_test.undefined + IS \'comment on undefined type\';', + regexp => + qr/^\QCOMMENT ON TYPE dump_test.undefined IS 'comment on undefined type';\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'COPY test_table' => { + create_order => 4, + create_sql => 'INSERT INTO dump_test.test_table (col1) ' + . 'SELECT generate_series FROM generate_series(1,9);', + regexp => qr/^ + \QCOPY dump_test.test_table (col1, col2, col3, col4) FROM stdin;\E + \n(?:\d\t\\N\t\\N\t\\N\n){9}\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + only_dump_test_table => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + exclude_test_table => 1, + exclude_test_table_data => 1, + schema_only => 1, + }, + }, + + 'COPY fk_reference_test_table' => { + create_order => 22, + create_sql => 'INSERT INTO dump_test.fk_reference_test_table (col1) ' + . 'SELECT generate_series FROM generate_series(1,5);', + regexp => qr/^ + \QCOPY dump_test.fk_reference_test_table (col1) FROM stdin;\E + \n(?:\d\n){5}\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + exclude_test_table => 1, + exclude_test_table_data => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + # In a data-only dump, we try to actually order according to FKs, + # so this check is just making sure that the referring table comes after + # the referred-to table. + 'COPY fk_reference_test_table second' => { + regexp => qr/^ + \QCOPY dump_test.test_table (col1, col2, col3, col4) FROM stdin;\E + \n(?:\d\t\\N\t\\N\t\\N\n){9}\\\.\n.* + \QCOPY dump_test.fk_reference_test_table (col1) FROM stdin;\E + \n(?:\d\n){5}\\\.\n + /xms, + like => { data_only => 1, }, + }, + + 'COPY test_second_table' => { + create_order => 7, + create_sql => 'INSERT INTO dump_test.test_second_table (col1, col2) ' + . 'SELECT generate_series, generate_series::text ' + . 'FROM generate_series(1,9);', + regexp => qr/^ + \QCOPY dump_test.test_second_table (col1, col2) FROM stdin;\E + \n(?:\d\t\d\n){9}\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'COPY test_third_table' => { + create_order => 7, + create_sql => + 'INSERT INTO dump_test.test_third_table VALUES (123, DEFAULT, 456);', + regexp => qr/^ + \QCOPY dump_test.test_third_table (f1, "F3") FROM stdin;\E + \n123\t456\n\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'COPY test_fourth_table' => { + create_order => 7, + create_sql => + 'INSERT INTO dump_test.test_fourth_table DEFAULT VALUES;' + . 'INSERT INTO dump_test.test_fourth_table DEFAULT VALUES;', + regexp => qr/^ + \QCOPY dump_test.test_fourth_table FROM stdin;\E + \n\n\n\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'COPY test_fifth_table' => { + create_order => 54, + create_sql => + 'INSERT INTO dump_test.test_fifth_table VALUES (NULL, true, false, \'11001\'::bit(5), \'NaN\');', + regexp => qr/^ + \QCOPY dump_test.test_fifth_table (col1, col2, col3, col4, col5) FROM stdin;\E + \n\\N\tt\tf\t11001\tNaN\n\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'COPY test_table_identity' => { + create_order => 54, + create_sql => + 'INSERT INTO dump_test.test_table_identity (col2) VALUES (\'test\');', + regexp => qr/^ + \QCOPY dump_test.test_table_identity (col1, col2) FROM stdin;\E + \n1\ttest\n\\\.\n + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + data_only => 1, + section_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'INSERT INTO test_table' => { + regexp => qr/^ + (?:INSERT\ INTO\ dump_test\.test_table\ \(col1,\ col2,\ col3,\ col4\)\ VALUES\ \(\d,\ NULL,\ NULL,\ NULL\);\n){9} + /xm, + like => { column_inserts => 1, }, + }, + + 'test_table with 4-row INSERTs' => { + regexp => qr/^ + (?: + INSERT\ INTO\ dump_test\.test_table\ VALUES\n + (?:\t\(\d,\ NULL,\ NULL,\ NULL\),\n){3} + \t\(\d,\ NULL,\ NULL,\ NULL\);\n + ){2} + INSERT\ INTO\ dump_test\.test_table\ VALUES\n + \t\(\d,\ NULL,\ NULL,\ NULL\); + /xm, + like => { rows_per_insert => 1, }, + }, + + 'INSERT INTO test_second_table' => { + regexp => qr/^ + (?:INSERT\ INTO\ dump_test\.test_second_table\ \(col1,\ col2\) + \ VALUES\ \(\d,\ '\d'\);\n){9}/xm, + like => { column_inserts => 1, }, + }, + + 'INSERT INTO test_third_table (colnames)' => { + regexp => + qr/^INSERT INTO dump_test\.test_third_table \(f1, "F3"\) VALUES \(123, 456\);\n/m, + like => { column_inserts => 1, }, + }, + + 'INSERT INTO test_third_table' => { + regexp => + qr/^INSERT INTO dump_test\.test_third_table VALUES \(123, DEFAULT, 456, DEFAULT\);\n/m, + like => { inserts => 1, }, + }, + + 'INSERT INTO test_fourth_table' => { + regexp => + qr/^(?:INSERT INTO dump_test\.test_fourth_table DEFAULT VALUES;\n){2}/m, + like => { column_inserts => 1, inserts => 1, rows_per_insert => 1, }, + }, + + 'INSERT INTO test_fifth_table' => { + regexp => + qr/^\QINSERT INTO dump_test.test_fifth_table (col1, col2, col3, col4, col5) VALUES (NULL, true, false, B'11001', 'NaN');\E/m, + like => { column_inserts => 1, }, + }, + + 'INSERT INTO test_table_identity' => { + regexp => + qr/^\QINSERT INTO dump_test.test_table_identity (col1, col2) OVERRIDING SYSTEM VALUE VALUES (1, 'test');\E/m, + like => { column_inserts => 1, }, + }, + + 'CREATE ROLE regress_dump_test_role' => { + create_order => 1, + create_sql => 'CREATE ROLE regress_dump_test_role;', + regexp => qr/^CREATE ROLE regress_dump_test_role;/m, + like => { + pg_dumpall_dbprivs => 1, + pg_dumpall_exclude => 1, + pg_dumpall_globals => 1, + pg_dumpall_globals_clean => 1, + }, + }, + + 'CREATE ACCESS METHOD gist2' => { + create_order => 52, + create_sql => + 'CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;', + regexp => + qr/CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE COLLATION test0 FROM "C"' => { + create_order => 76, + create_sql => 'CREATE COLLATION test0 FROM "C";', + regexp => + qr/CREATE COLLATION public.test0 \(provider = libc, locale = 'C'(, version = '[^']*')?\);/m, + collation => 1, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE CAST FOR timestamptz' => { + create_order => 51, + create_sql => + 'CREATE CAST (timestamptz AS interval) WITH FUNCTION age(timestamptz) AS ASSIGNMENT;', + regexp => + qr/CREATE CAST \(timestamp with time zone AS interval\) WITH FUNCTION pg_catalog\.age\(timestamp with time zone\) AS ASSIGNMENT;/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE DATABASE postgres' => { + regexp => qr/^ + \QCREATE DATABASE postgres WITH TEMPLATE = template0 \E + .+;/xm, + like => { createdb => 1, }, + }, + + 'CREATE DATABASE dump_test' => { + create_order => 47, + create_sql => 'CREATE DATABASE dump_test;', + regexp => qr/^ + \QCREATE DATABASE dump_test WITH TEMPLATE = template0 \E + .+;/xm, + like => { pg_dumpall_dbprivs => 1, }, + }, + + "CREATE DATABASE dump_test2 LOCALE = 'C'" => { + create_order => 47, + create_sql => + "CREATE DATABASE dump_test2 LOCALE = 'C' TEMPLATE = template0;", + regexp => qr/^ + \QCREATE DATABASE dump_test2 \E.*\QLOCALE = 'C';\E + /xm, + like => { pg_dumpall_dbprivs => 1, }, + }, + + 'CREATE EXTENSION ... plpgsql' => { + regexp => qr/^ + \QCREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;\E + /xm, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'CREATE AGGREGATE dump_test.newavg' => { + create_order => 25, + create_sql => 'CREATE AGGREGATE dump_test.newavg ( + sfunc = int4_avg_accum, + basetype = int4, + stype = _int8, + finalfunc = int8_avg, + finalfunc_modify = shareable, + initcond1 = \'{0,0}\' + );', + regexp => qr/^ + \QCREATE AGGREGATE dump_test.newavg(integer) (\E + \n\s+\QSFUNC = int4_avg_accum,\E + \n\s+\QSTYPE = bigint[],\E + \n\s+\QINITCOND = '{0,0}',\E + \n\s+\QFINALFUNC = int8_avg,\E + \n\s+\QFINALFUNC_MODIFY = SHAREABLE\E + \n\);/xm, + like => { + %full_runs, + %dump_test_schema_runs, + exclude_test_table => 1, + section_pre_data => 1, + }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE CONVERSION dump_test.test_conversion' => { + create_order => 78, + create_sql => + 'CREATE DEFAULT CONVERSION dump_test.test_conversion FOR \'LATIN1\' TO \'UTF8\' FROM iso8859_1_to_utf8;', + regexp => + qr/^\QCREATE DEFAULT CONVERSION dump_test.test_conversion FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;\E/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE DOMAIN dump_test.us_postal_code' => { + create_order => 29, + create_sql => 'CREATE DOMAIN dump_test.us_postal_code AS TEXT + COLLATE "C" + DEFAULT \'10014\' + CHECK(VALUE ~ \'^\d{5}$\' OR + VALUE ~ \'^\d{5}-\d{4}$\');', + regexp => qr/^ + \QCREATE DOMAIN dump_test.us_postal_code AS text COLLATE pg_catalog."C" DEFAULT '10014'::text\E\n\s+ + \QCONSTRAINT us_postal_code_check CHECK \E + \Q(((VALUE ~ '^\d{5}\E + \$\Q'::text) OR (VALUE ~ '^\d{5}-\d{4}\E\$ + \Q'::text)));\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION dump_test.pltestlang_call_handler' => { + create_order => 17, + create_sql => 'CREATE FUNCTION dump_test.pltestlang_call_handler() + RETURNS LANGUAGE_HANDLER AS \'$libdir/plpgsql\', + \'plpgsql_call_handler\' LANGUAGE C;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.pltestlang_call_handler() \E + \QRETURNS language_handler\E + \n\s+\QLANGUAGE c\E + \n\s+AS\ \'\$ + \Qlibdir\/plpgsql', 'plpgsql_call_handler';\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION dump_test.trigger_func' => { + create_order => 30, + create_sql => 'CREATE FUNCTION dump_test.trigger_func() + RETURNS trigger LANGUAGE plpgsql + AS $$ BEGIN RETURN NULL; END;$$;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.trigger_func() RETURNS trigger\E + \n\s+\QLANGUAGE plpgsql\E + \n\s+AS\ \$\$ + \Q BEGIN RETURN NULL; END;\E + \$\$;/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION dump_test.event_trigger_func' => { + create_order => 32, + create_sql => 'CREATE FUNCTION dump_test.event_trigger_func() + RETURNS event_trigger LANGUAGE plpgsql + AS $$ BEGIN RETURN; END;$$;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.event_trigger_func() RETURNS event_trigger\E + \n\s+\QLANGUAGE plpgsql\E + \n\s+AS\ \$\$ + \Q BEGIN RETURN; END;\E + \$\$;/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE OPERATOR FAMILY dump_test.op_family' => { + create_order => 73, + create_sql => + 'CREATE OPERATOR FAMILY dump_test.op_family USING btree;', + regexp => qr/^ + \QCREATE OPERATOR FAMILY dump_test.op_family USING btree;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE OPERATOR CLASS dump_test.op_class' => { + create_order => 74, + create_sql => 'CREATE OPERATOR CLASS dump_test.op_class + FOR TYPE bigint USING btree FAMILY dump_test.op_family + AS STORAGE bigint, + OPERATOR 1 <(bigint,bigint), + OPERATOR 2 <=(bigint,bigint), + OPERATOR 3 =(bigint,bigint), + OPERATOR 4 >=(bigint,bigint), + OPERATOR 5 >(bigint,bigint), + FUNCTION 1 btint8cmp(bigint,bigint), + FUNCTION 2 btint8sortsupport(internal), + FUNCTION 4 btequalimage(oid);', + # note: it's correct that btint8sortsupport and btequalimage + # are NOT included here (they're optional support functions): + regexp => qr/^ + \QCREATE OPERATOR CLASS dump_test.op_class\E\n\s+ + \QFOR TYPE bigint USING btree FAMILY dump_test.op_family AS\E\n\s+ + \QOPERATOR 1 <(bigint,bigint) ,\E\n\s+ + \QOPERATOR 2 <=(bigint,bigint) ,\E\n\s+ + \QOPERATOR 3 =(bigint,bigint) ,\E\n\s+ + \QOPERATOR 4 >=(bigint,bigint) ,\E\n\s+ + \QOPERATOR 5 >(bigint,bigint) ,\E\n\s+ + \QFUNCTION 1 (bigint, bigint) btint8cmp(bigint,bigint);\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + # verify that a custom operator/opclass/range type is dumped in right order + 'CREATE OPERATOR CLASS dump_test.op_class_custom' => { + create_order => 74, + create_sql => 'CREATE OPERATOR dump_test.~~ ( + PROCEDURE = int4eq, + LEFTARG = int, + RIGHTARG = int); + CREATE OPERATOR CLASS dump_test.op_class_custom + FOR TYPE int USING btree AS + OPERATOR 3 dump_test.~~; + CREATE TYPE dump_test.range_type_custom AS RANGE ( + subtype = int, + subtype_opclass = dump_test.op_class_custom);', + regexp => qr/^ + \QCREATE OPERATOR dump_test.~~ (\E\n.+ + \QCREATE OPERATOR FAMILY dump_test.op_class_custom USING btree;\E\n.+ + \QCREATE OPERATOR CLASS dump_test.op_class_custom\E\n\s+ + \QFOR TYPE integer USING btree FAMILY dump_test.op_class_custom AS\E\n\s+ + \QOPERATOR 3 dump_test.~~(integer,integer);\E\n.+ + \QCREATE TYPE dump_test.range_type_custom AS RANGE (\E\n\s+ + \Qsubtype = integer,\E\n\s+ + \Qmultirange_type_name = dump_test.multirange_type_custom,\E\n\s+ + \Qsubtype_opclass = dump_test.op_class_custom\E\n + \Q);\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE OPERATOR CLASS dump_test.op_class_empty' => { + create_order => 89, + create_sql => 'CREATE OPERATOR CLASS dump_test.op_class_empty + FOR TYPE bigint USING btree FAMILY dump_test.op_family + AS STORAGE bigint;', + regexp => qr/^ + \QCREATE OPERATOR CLASS dump_test.op_class_empty\E\n\s+ + \QFOR TYPE bigint USING btree FAMILY dump_test.op_family AS\E\n\s+ + \QSTORAGE bigint;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE EVENT TRIGGER test_event_trigger' => { + create_order => 33, + create_sql => 'CREATE EVENT TRIGGER test_event_trigger + ON ddl_command_start + EXECUTE FUNCTION dump_test.event_trigger_func();', + regexp => qr/^ + \QCREATE EVENT TRIGGER test_event_trigger \E + \QON ddl_command_start\E + \n\s+\QEXECUTE FUNCTION dump_test.event_trigger_func();\E + /xm, + like => { %full_runs, section_post_data => 1, }, + }, + + 'CREATE TRIGGER test_trigger' => { + create_order => 31, + create_sql => 'CREATE TRIGGER test_trigger + BEFORE INSERT ON dump_test.test_table + FOR EACH ROW WHEN (NEW.col1 > 10) + EXECUTE FUNCTION dump_test.trigger_func();', + regexp => qr/^ + \QCREATE TRIGGER test_trigger BEFORE INSERT ON dump_test.test_table \E + \QFOR EACH ROW WHEN ((new.col1 > 10)) \E + \QEXECUTE FUNCTION dump_test.trigger_func();\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_test_table => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'CREATE TYPE dump_test.planets AS ENUM' => { + create_order => 37, + create_sql => 'CREATE TYPE dump_test.planets + AS ENUM ( \'venus\', \'earth\', \'mars\' );', + regexp => qr/^ + \QCREATE TYPE dump_test.planets AS ENUM (\E + \n\s+'venus', + \n\s+'earth', + \n\s+'mars' + \n\);/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'CREATE TYPE dump_test.planets AS ENUM pg_upgrade' => { + regexp => qr/^ + \QCREATE TYPE dump_test.planets AS ENUM (\E + \n\);.*^ + \QALTER TYPE dump_test.planets ADD VALUE 'venus';\E + \n.*^ + \QALTER TYPE dump_test.planets ADD VALUE 'earth';\E + \n.*^ + \QALTER TYPE dump_test.planets ADD VALUE 'mars';\E + \n/xms, + like => { binary_upgrade => 1, }, + }, + + 'CREATE TYPE dump_test.textrange AS RANGE' => { + create_order => 38, + create_sql => 'CREATE TYPE dump_test.textrange + AS RANGE (subtype=text, collation="C");', + regexp => qr/^ + \QCREATE TYPE dump_test.textrange AS RANGE (\E + \n\s+\Qsubtype = text,\E + \n\s+\Qmultirange_type_name = dump_test.textmultirange,\E + \n\s+\Qcollation = pg_catalog."C"\E + \n\);/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TYPE dump_test.int42' => { + create_order => 39, + create_sql => 'CREATE TYPE dump_test.int42;', + regexp => qr/^\QCREATE TYPE dump_test.int42;\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1' => { + create_order => 80, + create_sql => + 'CREATE TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 (copy=english);', + regexp => qr/^ + \QCREATE TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 (\E\n + \s+\QPARSER = pg_catalog."default" );\E/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'ALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1 ...' => { + regexp => qr/^ + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR asciiword WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR word WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR numword WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR email WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR url WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR host WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR sfloat WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR version WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR hword_numpart WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR hword_part WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR hword_asciipart WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR numhword WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR asciihword WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR hword WITH english_stem;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR url_path WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR file WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR "float" WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR "int" WITH simple;\E\n + \n + \QALTER TEXT SEARCH CONFIGURATION dump_test.alt_ts_conf1\E\n + \s+\QADD MAPPING FOR uint WITH simple;\E\n + \n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1' => { + create_order => 81, + create_sql => + 'CREATE TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1 (lexize=dsimple_lexize);', + regexp => qr/^ + \QCREATE TEXT SEARCH TEMPLATE dump_test.alt_ts_temp1 (\E\n + \s+\QLEXIZE = dsimple_lexize );\E/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TEXT SEARCH PARSER dump_test.alt_ts_prs1' => { + create_order => 82, + create_sql => 'CREATE TEXT SEARCH PARSER dump_test.alt_ts_prs1 + (start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype);', + regexp => qr/^ + \QCREATE TEXT SEARCH PARSER dump_test.alt_ts_prs1 (\E\n + \s+\QSTART = prsd_start,\E\n + \s+\QGETTOKEN = prsd_nexttoken,\E\n + \s+\QEND = prsd_end,\E\n + \s+\QLEXTYPES = prsd_lextype );\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1' => { + create_order => 83, + create_sql => + 'CREATE TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 (template=simple);', + regexp => qr/^ + \QCREATE TEXT SEARCH DICTIONARY dump_test.alt_ts_dict1 (\E\n + \s+\QTEMPLATE = pg_catalog.simple );\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION dump_test.int42_in' => { + create_order => 40, + create_sql => 'CREATE FUNCTION dump_test.int42_in(cstring) + RETURNS dump_test.int42 AS \'int4in\' + LANGUAGE internal STRICT IMMUTABLE;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.int42_in(cstring) RETURNS dump_test.int42\E + \n\s+\QLANGUAGE internal IMMUTABLE STRICT\E + \n\s+AS\ \$\$int4in\$\$; + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION dump_test.int42_out' => { + create_order => 41, + create_sql => 'CREATE FUNCTION dump_test.int42_out(dump_test.int42) + RETURNS cstring AS \'int4out\' + LANGUAGE internal STRICT IMMUTABLE;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.int42_out(dump_test.int42) RETURNS cstring\E + \n\s+\QLANGUAGE internal IMMUTABLE STRICT\E + \n\s+AS\ \$\$int4out\$\$; + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FUNCTION ... SUPPORT' => { + create_order => 41, + create_sql => + 'CREATE FUNCTION dump_test.func_with_support() RETURNS int LANGUAGE sql AS $$ SELECT 1 $$ SUPPORT varchar_support;', + regexp => qr/^ + \QCREATE FUNCTION dump_test.func_with_support() RETURNS integer\E + \n\s+\QLANGUAGE sql SUPPORT varchar_support\E + \n\s+AS\ \$\$\Q SELECT 1 \E\$\$; + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE PROCEDURE dump_test.ptest1' => { + create_order => 41, + create_sql => 'CREATE PROCEDURE dump_test.ptest1(a int) + LANGUAGE SQL AS $$ INSERT INTO dump_test.test_table (col1) VALUES (a) $$;', + regexp => qr/^ + \QCREATE PROCEDURE dump_test.ptest1(IN a integer)\E + \n\s+\QLANGUAGE sql\E + \n\s+AS\ \$\$\Q INSERT INTO dump_test.test_table (col1) VALUES (a) \E\$\$; + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TYPE dump_test.int42 populated' => { + create_order => 42, + create_sql => 'CREATE TYPE dump_test.int42 ( + internallength = 4, + input = dump_test.int42_in, + output = dump_test.int42_out, + alignment = int4, + default = 42, + passedbyvalue);', + regexp => qr/^ + \QCREATE TYPE dump_test.int42 (\E + \n\s+\QINTERNALLENGTH = 4,\E + \n\s+\QINPUT = dump_test.int42_in,\E + \n\s+\QOUTPUT = dump_test.int42_out,\E + \n\s+\QDEFAULT = '42',\E + \n\s+\QALIGNMENT = int4,\E + \n\s+\QSTORAGE = plain,\E + \n\s+PASSEDBYVALUE\n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TYPE dump_test.composite' => { + create_order => 43, + create_sql => 'CREATE TYPE dump_test.composite AS ( + f1 int, + f2 dump_test.int42 + );', + regexp => qr/^ + \QCREATE TYPE dump_test.composite AS (\E + \n\s+\Qf1 integer,\E + \n\s+\Qf2 dump_test.int42\E + \n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TYPE dump_test.undefined' => { + create_order => 39, + create_sql => 'CREATE TYPE dump_test.undefined;', + regexp => qr/^\QCREATE TYPE dump_test.undefined;\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE FOREIGN DATA WRAPPER dummy' => { + create_order => 35, + create_sql => 'CREATE FOREIGN DATA WRAPPER dummy;', + regexp => qr/CREATE FOREIGN DATA WRAPPER dummy;/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE SERVER s1 FOREIGN DATA WRAPPER dummy' => { + create_order => 36, + create_sql => 'CREATE SERVER s1 FOREIGN DATA WRAPPER dummy;', + regexp => qr/CREATE SERVER s1 FOREIGN DATA WRAPPER dummy;/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE FOREIGN TABLE dump_test.foreign_table SERVER s1' => { + create_order => 88, + create_sql => + 'CREATE FOREIGN TABLE dump_test.foreign_table (c1 int options (column_name \'col1\')) + SERVER s1 OPTIONS (schema_name \'x1\');', + regexp => qr/ + \QCREATE FOREIGN TABLE dump_test.foreign_table (\E\n + \s+\Qc1 integer\E\n + \Q)\E\n + \QSERVER s1\E\n + \QOPTIONS (\E\n + \s+\Qschema_name 'x1'\E\n + \Q);\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE USER MAPPING FOR regress_dump_test_role SERVER s1' => { + create_order => 86, + create_sql => + 'CREATE USER MAPPING FOR regress_dump_test_role SERVER s1;', + regexp => + qr/CREATE USER MAPPING FOR regress_dump_test_role SERVER s1;/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE TRANSFORM FOR int' => { + create_order => 34, + create_sql => + 'CREATE TRANSFORM FOR int LANGUAGE SQL (FROM SQL WITH FUNCTION prsd_lextype(internal), TO SQL WITH FUNCTION int4recv(internal));', + regexp => + qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog\.prsd_lextype\(internal\), TO SQL WITH FUNCTION pg_catalog\.int4recv\(internal\)\);/m, + like => { %full_runs, section_pre_data => 1, }, + }, + + 'CREATE LANGUAGE pltestlang' => { + create_order => 18, + create_sql => 'CREATE LANGUAGE pltestlang + HANDLER dump_test.pltestlang_call_handler;', + regexp => qr/^ + \QCREATE PROCEDURAL LANGUAGE pltestlang \E + \QHANDLER dump_test.pltestlang_call_handler;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE MATERIALIZED VIEW matview' => { + create_order => 20, + create_sql => 'CREATE MATERIALIZED VIEW dump_test.matview (col1) AS + SELECT col1 FROM dump_test.test_table;', + regexp => qr/^ + \QCREATE MATERIALIZED VIEW dump_test.matview AS\E + \n\s+\QSELECT test_table.col1\E + \n\s+\QFROM dump_test.test_table\E + \n\s+\QWITH NO DATA;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE MATERIALIZED VIEW matview_second' => { + create_order => 21, + create_sql => 'CREATE MATERIALIZED VIEW + dump_test.matview_second (col1) AS + SELECT * FROM dump_test.matview;', + regexp => qr/^ + \QCREATE MATERIALIZED VIEW dump_test.matview_second AS\E + \n\s+\QSELECT matview.col1\E + \n\s+\QFROM dump_test.matview\E + \n\s+\QWITH NO DATA;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE MATERIALIZED VIEW matview_third' => { + create_order => 58, + create_sql => 'CREATE MATERIALIZED VIEW + dump_test.matview_third (col1) AS + SELECT * FROM dump_test.matview_second WITH NO DATA;', + regexp => qr/^ + \QCREATE MATERIALIZED VIEW dump_test.matview_third AS\E + \n\s+\QSELECT matview_second.col1\E + \n\s+\QFROM dump_test.matview_second\E + \n\s+\QWITH NO DATA;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE MATERIALIZED VIEW matview_fourth' => { + create_order => 59, + create_sql => 'CREATE MATERIALIZED VIEW + dump_test.matview_fourth (col1) AS + SELECT * FROM dump_test.matview_third WITH NO DATA;', + regexp => qr/^ + \QCREATE MATERIALIZED VIEW dump_test.matview_fourth AS\E + \n\s+\QSELECT matview_third.col1\E + \n\s+\QFROM dump_test.matview_third\E + \n\s+\QWITH NO DATA;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE MATERIALIZED VIEW matview_compression' => { + create_order => 20, + create_sql => 'CREATE MATERIALIZED VIEW + dump_test.matview_compression (col2) AS + SELECT col2 FROM dump_test.test_table; + ALTER MATERIALIZED VIEW dump_test.matview_compression + ALTER COLUMN col2 SET COMPRESSION lz4;', + regexp => qr/^ + \QCREATE MATERIALIZED VIEW dump_test.matview_compression AS\E + \n\s+\QSELECT test_table.col2\E + \n\s+\QFROM dump_test.test_table\E + \n\s+\QWITH NO DATA;\E + .* + \QALTER TABLE ONLY dump_test.matview_compression ALTER COLUMN col2 SET COMPRESSION lz4;\E\n + /xms, + lz4 => 1, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => + { exclude_dump_test_schema => 1, no_toast_compression => 1, }, + }, + + 'CREATE POLICY p1 ON test_table' => { + create_order => 22, + create_sql => 'CREATE POLICY p1 ON dump_test.test_table + USING (true) + WITH CHECK (true);', + regexp => qr/^ + \QCREATE POLICY p1 ON dump_test.test_table \E + \QUSING (true) WITH CHECK (true);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE POLICY p2 ON test_table FOR SELECT' => { + create_order => 24, + create_sql => 'CREATE POLICY p2 ON dump_test.test_table + FOR SELECT TO regress_dump_test_role USING (true);', + regexp => qr/^ + \QCREATE POLICY p2 ON dump_test.test_table FOR SELECT TO regress_dump_test_role \E + \QUSING (true);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE POLICY p3 ON test_table FOR INSERT' => { + create_order => 25, + create_sql => 'CREATE POLICY p3 ON dump_test.test_table + FOR INSERT TO regress_dump_test_role WITH CHECK (true);', + regexp => qr/^ + \QCREATE POLICY p3 ON dump_test.test_table FOR INSERT \E + \QTO regress_dump_test_role WITH CHECK (true);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE POLICY p4 ON test_table FOR UPDATE' => { + create_order => 26, + create_sql => 'CREATE POLICY p4 ON dump_test.test_table FOR UPDATE + TO regress_dump_test_role USING (true) WITH CHECK (true);', + regexp => qr/^ + \QCREATE POLICY p4 ON dump_test.test_table FOR UPDATE TO regress_dump_test_role \E + \QUSING (true) WITH CHECK (true);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE POLICY p5 ON test_table FOR DELETE' => { + create_order => 27, + create_sql => 'CREATE POLICY p5 ON dump_test.test_table + FOR DELETE TO regress_dump_test_role USING (true);', + regexp => qr/^ + \QCREATE POLICY p5 ON dump_test.test_table FOR DELETE \E + \QTO regress_dump_test_role USING (true);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE POLICY p6 ON test_table AS RESTRICTIVE' => { + create_order => 27, + create_sql => 'CREATE POLICY p6 ON dump_test.test_table AS RESTRICTIVE + USING (false);', + regexp => qr/^ + \QCREATE POLICY p6 ON dump_test.test_table AS RESTRICTIVE \E + \QUSING (false);\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE PUBLICATION pub1' => { + create_order => 50, + create_sql => 'CREATE PUBLICATION pub1;', + regexp => qr/^ + \QCREATE PUBLICATION pub1 WITH (publish = 'insert, update, delete, truncate');\E + /xm, + like => { %full_runs, section_post_data => 1, }, + }, + + 'CREATE PUBLICATION pub2' => { + create_order => 50, + create_sql => 'CREATE PUBLICATION pub2 + FOR ALL TABLES + WITH (publish = \'\');', + regexp => qr/^ + \QCREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish = '');\E + /xm, + like => { %full_runs, section_post_data => 1, }, + }, + + 'CREATE SUBSCRIPTION sub1' => { + create_order => 50, + create_sql => 'CREATE SUBSCRIPTION sub1 + CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 + WITH (connect = false);', + regexp => qr/^ + \QCREATE SUBSCRIPTION sub1 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub1');\E + /xm, + like => { %full_runs, section_post_data => 1, }, + }, + + 'ALTER PUBLICATION pub1 ADD TABLE test_table' => { + create_order => 51, + create_sql => + 'ALTER PUBLICATION pub1 ADD TABLE dump_test.test_table;', + regexp => qr/^ + \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_table;\E + /xm, + like => { %full_runs, section_post_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'ALTER PUBLICATION pub1 ADD TABLE test_second_table' => { + create_order => 52, + create_sql => + 'ALTER PUBLICATION pub1 ADD TABLE dump_test.test_second_table;', + regexp => qr/^ + \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_second_table;\E + /xm, + like => { %full_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE SCHEMA public' => { + regexp => qr/^CREATE SCHEMA public;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'CREATE SCHEMA dump_test' => { + create_order => 2, + create_sql => 'CREATE SCHEMA dump_test;', + regexp => qr/^CREATE SCHEMA dump_test;/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE SCHEMA dump_test_second_schema' => { + create_order => 9, + create_sql => 'CREATE SCHEMA dump_test_second_schema;', + regexp => qr/^CREATE SCHEMA dump_test_second_schema;/m, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + }, + }, + + 'CREATE TABLE test_table' => { + create_order => 3, + create_sql => 'CREATE TABLE dump_test.test_table ( + col1 serial primary key, + col2 text COMPRESSION pglz, + col3 text, + col4 text, + CHECK (col1 <= 1000) + ) WITH (autovacuum_enabled = false, fillfactor=80);', + regexp => qr/^ + \QCREATE TABLE dump_test.test_table (\E\n + \s+\Qcol1 integer NOT NULL,\E\n + \s+\Qcol2 text,\E\n + \s+\Qcol3 text,\E\n + \s+\Qcol4 text,\E\n + \s+\QCONSTRAINT test_table_col1_check CHECK ((col1 <= 1000))\E\n + \Q)\E\n + \QWITH (autovacuum_enabled='false', fillfactor='80');\E\n/xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + }, + }, + + 'CREATE TABLE fk_reference_test_table' => { + create_order => 21, + create_sql => 'CREATE TABLE dump_test.fk_reference_test_table ( + col1 int primary key references dump_test.test_table + );', + regexp => qr/^ + \QCREATE TABLE dump_test.fk_reference_test_table (\E + \n\s+\Qcol1 integer NOT NULL\E + \n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_second_table' => { + create_order => 6, + create_sql => 'CREATE TABLE dump_test.test_second_table ( + col1 int, + col2 text + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_second_table (\E + \n\s+\Qcol1 integer,\E + \n\s+\Qcol2 text\E + \n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_compression' => { + create_order => 3, + create_sql => 'CREATE TABLE dump_test.test_compression ( + col1 int, + col2 text COMPRESSION lz4 + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_compression (\E\n + \s+\Qcol1 integer,\E\n + \s+\Qcol2 text\E\n + \);\n + .* + \QALTER TABLE ONLY dump_test.test_compression ALTER COLUMN col2 SET COMPRESSION lz4;\E\n + /xms, + lz4 => 1, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => + { exclude_dump_test_schema => 1, no_toast_compression => 1, }, + }, + + 'CREATE TABLE measurement PARTITIONED BY' => { + create_order => 90, + create_sql => 'CREATE TABLE dump_test.measurement ( + city_id serial not null, + logdate date not null, + peaktemp int CHECK (peaktemp >= -460), + unitsales int + ) PARTITION BY RANGE (logdate);', + regexp => qr/^ + \Q-- Name: measurement;\E.*\n + \Q--\E\n\n + \QCREATE TABLE dump_test.measurement (\E\n + \s+\Qcity_id integer NOT NULL,\E\n + \s+\Qlogdate date NOT NULL,\E\n + \s+\Qpeaktemp integer,\E\n + \s+\Qunitsales integer,\E\n + \s+\QCONSTRAINT measurement_peaktemp_check CHECK ((peaktemp >= '-460'::integer))\E\n + \)\n + \QPARTITION BY RANGE (logdate);\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'Partition measurement_y2006m2 creation' => { + create_order => 91, + create_sql => + 'CREATE TABLE dump_test_second_schema.measurement_y2006m2 + PARTITION OF dump_test.measurement ( + unitsales DEFAULT 0 CHECK (unitsales >= 0) + ) + FOR VALUES FROM (\'2006-02-01\') TO (\'2006-03-01\');', + regexp => qr/^ + \QCREATE TABLE dump_test_second_schema.measurement_y2006m2 (\E\n + \s+\Qcity_id integer DEFAULT nextval('dump_test.measurement_city_id_seq'::regclass) NOT NULL,\E\n + \s+\Qlogdate date NOT NULL,\E\n + \s+\Qpeaktemp integer,\E\n + \s+\Qunitsales integer DEFAULT 0,\E\n + \s+\QCONSTRAINT measurement_peaktemp_check CHECK ((peaktemp >= '-460'::integer)),\E\n + \s+\QCONSTRAINT measurement_y2006m2_unitsales_check CHECK ((unitsales >= 0))\E\n + \);\n + /xm, + like => { + %full_runs, + section_pre_data => 1, + role => 1, + binary_upgrade => 1, + }, + }, + + 'Creation of row-level trigger in partitioned table' => { + create_order => 92, + create_sql => 'CREATE TRIGGER test_trigger + AFTER INSERT ON dump_test.measurement + FOR EACH ROW EXECUTE PROCEDURE dump_test.trigger_func()', + regexp => qr/^ + \QCREATE TRIGGER test_trigger AFTER INSERT ON dump_test.measurement \E + \QFOR EACH ROW \E + \QEXECUTE FUNCTION dump_test.trigger_func();\E + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + }, + }, + + 'Disabled trigger on partition is altered' => { + create_order => 93, + create_sql => + 'CREATE TABLE dump_test_second_schema.measurement_y2006m3 + PARTITION OF dump_test.measurement + FOR VALUES FROM (\'2006-03-01\') TO (\'2006-04-01\'); + ALTER TABLE dump_test_second_schema.measurement_y2006m3 DISABLE TRIGGER test_trigger; + CREATE TABLE dump_test_second_schema.measurement_y2006m4 + PARTITION OF dump_test.measurement + FOR VALUES FROM (\'2006-04-01\') TO (\'2006-05-01\'); + ALTER TABLE dump_test_second_schema.measurement_y2006m4 ENABLE REPLICA TRIGGER test_trigger; + CREATE TABLE dump_test_second_schema.measurement_y2006m5 + PARTITION OF dump_test.measurement + FOR VALUES FROM (\'2006-05-01\') TO (\'2006-06-01\'); + ALTER TABLE dump_test_second_schema.measurement_y2006m5 ENABLE ALWAYS TRIGGER test_trigger; + ', + regexp => qr/^ + \QALTER TABLE dump_test_second_schema.measurement_y2006m3 DISABLE TRIGGER test_trigger;\E + /xm, + like => { + %full_runs, + section_post_data => 1, + role => 1, + binary_upgrade => 1, + }, + }, + + 'Replica trigger on partition is altered' => { + regexp => qr/^ + \QALTER TABLE dump_test_second_schema.measurement_y2006m4 ENABLE REPLICA TRIGGER test_trigger;\E + /xm, + like => { + %full_runs, + section_post_data => 1, + role => 1, + binary_upgrade => 1, + }, + }, + + 'Always trigger on partition is altered' => { + regexp => qr/^ + \QALTER TABLE dump_test_second_schema.measurement_y2006m5 ENABLE ALWAYS TRIGGER test_trigger;\E + /xm, + like => { + %full_runs, + section_post_data => 1, + role => 1, + binary_upgrade => 1, + }, + }, + + # We should never see the creation of a trigger on a partition + 'Disabled trigger on partition is not created' => { + regexp => qr/CREATE TRIGGER test_trigger.*ON dump_test_second_schema/, + like => {}, + unlike => { %full_runs, %dump_test_schema_runs }, + }, + + # Triggers on partitions should not be dropped individually + 'Triggers on partitions are not dropped' => { + regexp => qr/DROP TRIGGER test_trigger.*ON dump_test_second_schema/, + like => {} + }, + + 'CREATE TABLE test_third_table_generated_cols' => { + create_order => 6, + create_sql => 'CREATE TABLE dump_test.test_third_table ( + f1 int, junk int, + g1 int generated always as (f1 * 2) stored, + "F3" int, + g2 int generated always as ("F3" * 3) stored + ); + ALTER TABLE dump_test.test_third_table DROP COLUMN junk;', + regexp => qr/^ + \QCREATE TABLE dump_test.test_third_table (\E\n + \s+\Qf1 integer,\E\n + \s+\Qg1 integer GENERATED ALWAYS AS ((f1 * 2)) STORED,\E\n + \s+\Q"F3" integer,\E\n + \s+\Qg2 integer GENERATED ALWAYS AS (("F3" * 3)) STORED\E\n + \);\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_fourth_table_zero_col' => { + create_order => 6, + create_sql => 'CREATE TABLE dump_test.test_fourth_table ( + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_fourth_table (\E + \n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_fifth_table' => { + create_order => 53, + create_sql => 'CREATE TABLE dump_test.test_fifth_table ( + col1 integer, + col2 boolean, + col3 boolean, + col4 bit(5), + col5 float8 + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_fifth_table (\E + \n\s+\Qcol1 integer,\E + \n\s+\Qcol2 boolean,\E + \n\s+\Qcol3 boolean,\E + \n\s+\Qcol4 bit(5),\E + \n\s+\Qcol5 double precision\E + \n\); + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_table_identity' => { + create_order => 3, + create_sql => 'CREATE TABLE dump_test.test_table_identity ( + col1 int generated always as identity primary key, + col2 text + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_identity (\E\n + \s+\Qcol1 integer NOT NULL,\E\n + \s+\Qcol2 text\E\n + \); + .* + \QALTER TABLE dump_test.test_table_identity ALTER COLUMN col1 ADD GENERATED ALWAYS AS IDENTITY (\E\n + \s+\QSEQUENCE NAME dump_test.test_table_identity_col1_seq\E\n + \s+\QSTART WITH 1\E\n + \s+\QINCREMENT BY 1\E\n + \s+\QNO MINVALUE\E\n + \s+\QNO MAXVALUE\E\n + \s+\QCACHE 1\E\n + \); + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_table_generated' => { + create_order => 3, + create_sql => 'CREATE TABLE dump_test.test_table_generated ( + col1 int primary key, + col2 int generated always as (col1 * 2) stored + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_generated (\E\n + \s+\Qcol1 integer NOT NULL,\E\n + \s+\Qcol2 integer GENERATED ALWAYS AS ((col1 * 2)) STORED\E\n + \); + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_table_generated_child1 (without local columns)' => { + create_order => 4, + create_sql => 'CREATE TABLE dump_test.test_table_generated_child1 () + INHERITS (dump_test.test_table_generated);', + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_generated_child1 (\E\n + \)\n + \QINHERITS (dump_test.test_table_generated);\E\n + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'ALTER TABLE test_table_generated_child1' => { + regexp => + qr/^\QALTER TABLE ONLY dump_test.test_table_generated_child1 ALTER COLUMN col2 \E/m, + + # should not get emitted + like => {}, + }, + + 'CREATE TABLE test_table_generated_child2 (with local columns)' => { + create_order => 4, + create_sql => 'CREATE TABLE dump_test.test_table_generated_child2 ( + col1 int, + col2 int + ) INHERITS (dump_test.test_table_generated);', + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_generated_child2 (\E\n + \s+\Qcol1 integer,\E\n + \s+\Qcol2 integer\E\n + \)\n + \QINHERITS (dump_test.test_table_generated);\E\n + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'CREATE TABLE table_with_stats' => { + create_order => 98, + create_sql => 'CREATE TABLE dump_test.table_index_stats ( + col1 int, + col2 int, + col3 int); + CREATE INDEX index_with_stats + ON dump_test.table_index_stats + ((col1 + 1), col1, (col2 + 1), (col3 + 1)); + ALTER INDEX dump_test.index_with_stats + ALTER COLUMN 1 SET STATISTICS 400; + ALTER INDEX dump_test.index_with_stats + ALTER COLUMN 3 SET STATISTICS 500;', + regexp => qr/^ + \QALTER INDEX dump_test.index_with_stats ALTER COLUMN 1 SET STATISTICS 400;\E\n + \QALTER INDEX dump_test.index_with_stats ALTER COLUMN 3 SET STATISTICS 500;\E\n + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_inheritance_parent' => { + create_order => 90, + create_sql => 'CREATE TABLE dump_test.test_inheritance_parent ( + col1 int NOT NULL, + col2 int CHECK (col2 >= 42) + );', + regexp => qr/^ + \QCREATE TABLE dump_test.test_inheritance_parent (\E\n + \s+\Qcol1 integer NOT NULL,\E\n + \s+\Qcol2 integer,\E\n + \s+\QCONSTRAINT test_inheritance_parent_col2_check CHECK ((col2 >= 42))\E\n + \Q);\E\n + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE TABLE test_inheritance_child' => { + create_order => 91, + create_sql => 'CREATE TABLE dump_test.test_inheritance_child ( + col1 int NOT NULL, + CONSTRAINT test_inheritance_child CHECK (col2 >= 142857) + ) INHERITS (dump_test.test_inheritance_parent);', + regexp => qr/^ + \QCREATE TABLE dump_test.test_inheritance_child (\E\n + \s+\Qcol1 integer,\E\n + \s+\QCONSTRAINT test_inheritance_child CHECK ((col2 >= 142857))\E\n + \)\n + \QINHERITS (dump_test.test_inheritance_parent);\E\n + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + }, + }, + + 'CREATE STATISTICS extended_stats_no_options' => { + create_order => 97, + create_sql => 'CREATE STATISTICS dump_test.test_ext_stats_no_options + ON col1, col2 FROM dump_test.test_fifth_table', + regexp => qr/^ + \QCREATE STATISTICS dump_test.test_ext_stats_no_options ON col1, col2 FROM dump_test.test_fifth_table;\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE STATISTICS extended_stats_options' => { + create_order => 97, + create_sql => 'CREATE STATISTICS dump_test.test_ext_stats_opts + (ndistinct) ON col1, col2 FROM dump_test.test_fifth_table', + regexp => qr/^ + \QCREATE STATISTICS dump_test.test_ext_stats_opts (ndistinct) ON col1, col2 FROM dump_test.test_fifth_table;\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'ALTER STATISTICS extended_stats_options' => { + create_order => 98, + create_sql => + 'ALTER STATISTICS dump_test.test_ext_stats_opts SET STATISTICS 1000', + regexp => qr/^ + \QALTER STATISTICS dump_test.test_ext_stats_opts SET STATISTICS 1000;\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE STATISTICS extended_stats_expression' => { + create_order => 99, + create_sql => 'CREATE STATISTICS dump_test.test_ext_stats_expr + ON (2 * col1) FROM dump_test.test_fifth_table', + regexp => qr/^ + \QCREATE STATISTICS dump_test.test_ext_stats_expr ON (2 * col1) FROM dump_test.test_fifth_table;\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE SEQUENCE test_table_col1_seq' => { + regexp => qr/^ + \QCREATE SEQUENCE dump_test.test_table_col1_seq\E + \n\s+\QAS integer\E + \n\s+\QSTART WITH 1\E + \n\s+\QINCREMENT BY 1\E + \n\s+\QNO MINVALUE\E + \n\s+\QNO MAXVALUE\E + \n\s+\QCACHE 1;\E + /xm, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE INDEX ON ONLY measurement' => { + create_order => 92, + create_sql => + 'CREATE INDEX ON dump_test.measurement (city_id, logdate);', + regexp => qr/^ + \QCREATE INDEX measurement_city_id_logdate_idx ON ONLY dump_test.measurement USING\E + /xm, + like => { + binary_upgrade => 1, + clean => 1, + clean_if_exists => 1, + createdb => 1, + defaults => 1, + exclude_test_table => 1, + exclude_test_table_data => 1, + no_toast_compression => 1, + no_blobs => 1, + no_privs => 1, + no_owner => 1, + only_dump_test_schema => 1, + pg_dumpall_dbprivs => 1, + pg_dumpall_exclude => 1, + schema_only => 1, + section_post_data => 1, + test_schema_plus_blobs => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_test_table => 1, + pg_dumpall_globals => 1, + pg_dumpall_globals_clean => 1, + role => 1, + section_pre_data => 1, + }, + }, + + 'ALTER TABLE measurement PRIMARY KEY' => { + all_runs => 1, + catch_all => 'CREATE ... commands', + create_order => 93, + create_sql => + 'ALTER TABLE dump_test.measurement ADD PRIMARY KEY (city_id, logdate);', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.measurement\E \n^\s+ + \QADD CONSTRAINT measurement_pkey PRIMARY KEY (city_id, logdate);\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'CREATE INDEX ... ON measurement_y2006_m2' => { + regexp => qr/^ + \QCREATE INDEX measurement_y2006m2_city_id_logdate_idx ON dump_test_second_schema.measurement_y2006m2 \E + /xm, + like => { + %full_runs, + role => 1, + section_post_data => 1, + }, + }, + + 'ALTER INDEX ... ATTACH PARTITION' => { + regexp => qr/^ + \QALTER INDEX dump_test.measurement_city_id_logdate_idx ATTACH PARTITION dump_test_second_schema.measurement_y2006m2_city_id_logdate_idx\E + /xm, + like => { + %full_runs, + role => 1, + section_post_data => 1, + }, + }, + + 'ALTER INDEX ... ATTACH PARTITION (primary key)' => { + all_runs => 1, + catch_all => 'CREATE ... commands', + regexp => qr/^ + \QALTER INDEX dump_test.measurement_pkey ATTACH PARTITION dump_test_second_schema.measurement_y2006m2_pkey\E + /xm, + like => { + binary_upgrade => 1, + clean => 1, + clean_if_exists => 1, + createdb => 1, + defaults => 1, + exclude_dump_test_schema => 1, + exclude_test_table => 1, + exclude_test_table_data => 1, + no_toast_compression => 1, + no_blobs => 1, + no_privs => 1, + no_owner => 1, + pg_dumpall_dbprivs => 1, + pg_dumpall_exclude => 1, + role => 1, + schema_only => 1, + section_post_data => 1, + }, + unlike => { + only_dump_test_schema => 1, + only_dump_test_table => 1, + pg_dumpall_globals => 1, + pg_dumpall_globals_clean => 1, + section_pre_data => 1, + test_schema_plus_blobs => 1, + }, + }, + + 'CREATE VIEW test_view' => { + create_order => 61, + create_sql => 'CREATE VIEW dump_test.test_view + WITH (check_option = \'local\', security_barrier = true) AS + SELECT col1 FROM dump_test.test_table;', + regexp => qr/^ + \QCREATE VIEW dump_test.test_view WITH (security_barrier='true') AS\E + \n\s+\QSELECT test_table.col1\E + \n\s+\QFROM dump_test.test_table\E + \n\s+\QWITH LOCAL CHECK OPTION;\E/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + 'ALTER VIEW test_view SET DEFAULT' => { + create_order => 62, + create_sql => + 'ALTER VIEW dump_test.test_view ALTER COLUMN col1 SET DEFAULT 1;', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_view ALTER COLUMN col1 SET DEFAULT 1;\E/xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { exclude_dump_test_schema => 1, }, + }, + + # FIXME + 'DROP SCHEMA public (for testing without public schema)' => { + database => 'regress_pg_dump_test', + create_order => 100, + create_sql => 'DROP SCHEMA public;', + regexp => qr/^DROP SCHEMA public;/m, + like => {}, + }, + + 'DROP SCHEMA public' => { + regexp => qr/^DROP SCHEMA public;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'DROP SCHEMA IF EXISTS public' => { + regexp => qr/^DROP SCHEMA IF EXISTS public;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'DROP EXTENSION plpgsql' => { + regexp => qr/^DROP EXTENSION plpgsql;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'DROP FUNCTION dump_test.pltestlang_call_handler()' => { + regexp => qr/^DROP FUNCTION dump_test\.pltestlang_call_handler\(\);/m, + like => { clean => 1, }, + }, + + 'DROP LANGUAGE pltestlang' => { + regexp => qr/^DROP PROCEDURAL LANGUAGE pltestlang;/m, + like => { clean => 1, }, + }, + + 'DROP SCHEMA dump_test' => { + regexp => qr/^DROP SCHEMA dump_test;/m, + like => { clean => 1, }, + }, + + 'DROP SCHEMA dump_test_second_schema' => { + regexp => qr/^DROP SCHEMA dump_test_second_schema;/m, + like => { clean => 1, }, + }, + + 'DROP TABLE test_table' => { + regexp => qr/^DROP TABLE dump_test\.test_table;/m, + like => { clean => 1, }, + }, + + 'DROP TABLE fk_reference_test_table' => { + regexp => qr/^DROP TABLE dump_test\.fk_reference_test_table;/m, + like => { clean => 1, }, + }, + + 'DROP TABLE test_second_table' => { + regexp => qr/^DROP TABLE dump_test\.test_second_table;/m, + like => { clean => 1, }, + }, + + 'DROP EXTENSION IF EXISTS plpgsql' => { + regexp => qr/^DROP EXTENSION IF EXISTS plpgsql;/m, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'DROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler()' => { + regexp => qr/^ + \QDROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler();\E + /xm, + like => { clean_if_exists => 1, }, + }, + + 'DROP LANGUAGE IF EXISTS pltestlang' => { + regexp => qr/^DROP PROCEDURAL LANGUAGE IF EXISTS pltestlang;/m, + like => { clean_if_exists => 1, }, + }, + + 'DROP SCHEMA IF EXISTS dump_test' => { + regexp => qr/^DROP SCHEMA IF EXISTS dump_test;/m, + like => { clean_if_exists => 1, }, + }, + + 'DROP SCHEMA IF EXISTS dump_test_second_schema' => { + regexp => qr/^DROP SCHEMA IF EXISTS dump_test_second_schema;/m, + like => { clean_if_exists => 1, }, + }, + + 'DROP TABLE IF EXISTS test_table' => { + regexp => qr/^DROP TABLE IF EXISTS dump_test\.test_table;/m, + like => { clean_if_exists => 1, }, + }, + + 'DROP TABLE IF EXISTS test_second_table' => { + regexp => qr/^DROP TABLE IF EXISTS dump_test\.test_second_table;/m, + like => { clean_if_exists => 1, }, + }, + + 'DROP ROLE regress_dump_test_role' => { + regexp => qr/^ + \QDROP ROLE regress_dump_test_role;\E + /xm, + like => { pg_dumpall_globals_clean => 1, }, + }, + + 'DROP ROLE pg_' => { + regexp => qr/^ + \QDROP ROLE pg_\E.+; + /xm, + + # this shouldn't ever get emitted anywhere + like => {}, + }, + + 'GRANT USAGE ON SCHEMA dump_test_second_schema' => { + create_order => 10, + create_sql => 'GRANT USAGE ON SCHEMA dump_test_second_schema + TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT USAGE ON SCHEMA dump_test_second_schema TO regress_dump_test_role;\E + /xm, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + }, + unlike => { no_privs => 1, }, + }, + + 'GRANT USAGE ON FOREIGN DATA WRAPPER dummy' => { + create_order => 85, + create_sql => 'GRANT USAGE ON FOREIGN DATA WRAPPER dummy + TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON FOREIGN DATA WRAPPER dummy TO regress_dump_test_role;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'GRANT USAGE ON FOREIGN SERVER s1' => { + create_order => 85, + create_sql => 'GRANT USAGE ON FOREIGN SERVER s1 + TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON FOREIGN SERVER s1 TO regress_dump_test_role;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'GRANT USAGE ON DOMAIN dump_test.us_postal_code' => { + create_order => 72, + create_sql => + 'GRANT USAGE ON DOMAIN dump_test.us_postal_code TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON TYPE dump_test.us_postal_code TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT USAGE ON TYPE dump_test.int42' => { + create_order => 87, + create_sql => + 'GRANT USAGE ON TYPE dump_test.int42 TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON TYPE dump_test.int42 TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT USAGE ON TYPE dump_test.planets - ENUM' => { + create_order => 66, + create_sql => + 'GRANT USAGE ON TYPE dump_test.planets TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON TYPE dump_test.planets TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT USAGE ON TYPE dump_test.textrange - RANGE' => { + create_order => 67, + create_sql => + 'GRANT USAGE ON TYPE dump_test.textrange TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON TYPE dump_test.textrange TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT CREATE ON DATABASE dump_test' => { + create_order => 48, + create_sql => + 'GRANT CREATE ON DATABASE dump_test TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT CREATE ON DATABASE dump_test TO regress_dump_test_role;\E + /xm, + like => { pg_dumpall_dbprivs => 1, }, + }, + + 'GRANT SELECT ON TABLE test_table' => { + create_order => 5, + create_sql => 'GRANT SELECT ON TABLE dump_test.test_table + TO regress_dump_test_role;', + regexp => + qr/^\QGRANT SELECT ON TABLE dump_test.test_table TO regress_dump_test_role;\E/m, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + exclude_test_table => 1, + no_privs => 1, + }, + }, + + 'GRANT SELECT ON TABLE measurement' => { + create_order => 91, + create_sql => 'GRANT SELECT ON + TABLE dump_test.measurement + TO regress_dump_test_role;', + regexp => + qr/^\QGRANT SELECT ON TABLE dump_test.measurement TO regress_dump_test_role;\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT SELECT ON TABLE measurement_y2006m2' => { + create_order => 94, + create_sql => 'GRANT SELECT ON TABLE + dump_test_second_schema.measurement_y2006m2, + dump_test_second_schema.measurement_y2006m3, + dump_test_second_schema.measurement_y2006m4, + dump_test_second_schema.measurement_y2006m5 + TO regress_dump_test_role;', + regexp => + qr/^\QGRANT SELECT ON TABLE dump_test_second_schema.measurement_y2006m2 TO regress_dump_test_role;\E/m, + like => { + %full_runs, + role => 1, + section_pre_data => 1, + }, + unlike => { no_privs => 1, }, + }, + + 'GRANT ALL ON LARGE OBJECT ...' => { + create_order => 60, + create_sql => 'DO $$ + DECLARE myoid oid; + BEGIN + SELECT loid FROM pg_largeobject INTO myoid; + EXECUTE \'GRANT ALL ON LARGE OBJECT \' || myoid || \' TO regress_dump_test_role;\'; + END; + $$;', + regexp => qr/^ + \QGRANT ALL ON LARGE OBJECT \E[0-9]+\Q TO regress_dump_test_role;\E + /xm, + like => { + %full_runs, + column_inserts => 1, + data_only => 1, + inserts => 1, + section_pre_data => 1, + test_schema_plus_blobs => 1, + binary_upgrade => 1, + }, + unlike => { + no_blobs => 1, + no_privs => 1, + schema_only => 1, + }, + }, + + 'GRANT INSERT(col1) ON TABLE test_second_table' => { + create_order => 8, + create_sql => + 'GRANT INSERT (col1) ON TABLE dump_test.test_second_table + TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT INSERT(col1) ON TABLE dump_test.test_second_table TO regress_dump_test_role;\E + /xm, + like => + { %full_runs, %dump_test_schema_runs, section_pre_data => 1, }, + unlike => { + exclude_dump_test_schema => 1, + no_privs => 1, + }, + }, + + 'GRANT EXECUTE ON FUNCTION pg_sleep() TO regress_dump_test_role' => { + create_order => 16, + create_sql => 'GRANT EXECUTE ON FUNCTION pg_sleep(float8) + TO regress_dump_test_role;', + regexp => qr/^ + \QGRANT ALL ON FUNCTION pg_catalog.pg_sleep(double precision) TO regress_dump_test_role;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'GRANT SELECT (proname ...) ON TABLE pg_proc TO public' => { + create_order => 46, + create_sql => 'GRANT SELECT ( + tableoid, + oid, + proname, + pronamespace, + proowner, + prolang, + procost, + prorows, + provariadic, + prosupport, + prokind, + prosecdef, + proleakproof, + proisstrict, + proretset, + provolatile, + proparallel, + pronargs, + pronargdefaults, + prorettype, + proargtypes, + proallargtypes, + proargmodes, + proargnames, + proargdefaults, + protrftypes, + prosrc, + probin, + proconfig, + proacl + ) ON TABLE pg_proc TO public;', + regexp => qr/ + \QGRANT SELECT(tableoid) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(oid) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proname) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(pronamespace) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proowner) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prolang) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(procost) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prorows) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(provariadic) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prosupport) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prokind) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prosecdef) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proleakproof) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proisstrict) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proretset) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(provolatile) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proparallel) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(pronargs) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(pronargdefaults) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prorettype) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proargtypes) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proallargtypes) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proargmodes) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proargnames) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proargdefaults) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(protrftypes) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prosrc) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(probin) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proconfig) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(proacl) ON TABLE pg_catalog.pg_proc TO PUBLIC;\E/xms, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'GRANT USAGE ON SCHEMA public TO public' => { + regexp => qr/^ + \Q--\E\n\n + \QGRANT USAGE ON SCHEMA public TO PUBLIC;\E + /xm, + + # this shouldn't ever get emitted anymore + like => {}, + }, + + 'REFRESH MATERIALIZED VIEW matview' => { + regexp => qr/^\QREFRESH MATERIALIZED VIEW dump_test.matview;\E/m, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + 'REFRESH MATERIALIZED VIEW matview_second' => { + regexp => qr/^ + \QREFRESH MATERIALIZED VIEW dump_test.matview;\E + \n.* + \QREFRESH MATERIALIZED VIEW dump_test.matview_second;\E + /xms, + like => + { %full_runs, %dump_test_schema_runs, section_post_data => 1, }, + unlike => { + binary_upgrade => 1, + exclude_dump_test_schema => 1, + schema_only => 1, + }, + }, + + # FIXME + 'REFRESH MATERIALIZED VIEW matview_third' => { + regexp => qr/^ + \QREFRESH MATERIALIZED VIEW dump_test.matview_third;\E + /xms, + like => {}, + }, + + # FIXME + 'REFRESH MATERIALIZED VIEW matview_fourth' => { + regexp => qr/^ + \QREFRESH MATERIALIZED VIEW dump_test.matview_fourth;\E + /xms, + like => {}, + }, + + 'REVOKE CONNECT ON DATABASE dump_test FROM public' => { + create_order => 49, + create_sql => 'REVOKE CONNECT ON DATABASE dump_test FROM public;', + regexp => qr/^ + \QREVOKE CONNECT,TEMPORARY ON DATABASE dump_test FROM PUBLIC;\E\n + \QGRANT TEMPORARY ON DATABASE dump_test TO PUBLIC;\E\n + \QGRANT CREATE ON DATABASE dump_test TO regress_dump_test_role;\E + /xm, + like => { pg_dumpall_dbprivs => 1, }, + }, + + 'REVOKE EXECUTE ON FUNCTION pg_sleep() FROM public' => { + create_order => 15, + create_sql => 'REVOKE EXECUTE ON FUNCTION pg_sleep(float8) + FROM public;', + regexp => qr/^ + \QREVOKE ALL ON FUNCTION pg_catalog.pg_sleep(double precision) FROM PUBLIC;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'REVOKE SELECT ON TABLE pg_proc FROM public' => { + create_order => 45, + create_sql => 'REVOKE SELECT ON TABLE pg_proc FROM public;', + regexp => + qr/^\QREVOKE SELECT ON TABLE pg_catalog.pg_proc FROM PUBLIC;\E/m, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'REVOKE CREATE ON SCHEMA public FROM public' => { + create_order => 16, + create_sql => 'REVOKE CREATE ON SCHEMA public FROM public;', + regexp => qr/^ + \QREVOKE ALL ON SCHEMA public FROM PUBLIC;\E + \n\QGRANT USAGE ON SCHEMA public TO PUBLIC;\E + /xm, + like => { %full_runs, section_pre_data => 1, }, + unlike => { no_privs => 1, }, + }, + + 'REVOKE USAGE ON LANGUAGE plpgsql FROM public' => { + create_order => 16, + create_sql => 'REVOKE USAGE ON LANGUAGE plpgsql FROM public;', + regexp => qr/^REVOKE ALL ON LANGUAGE plpgsql FROM PUBLIC;/m, + like => { + %full_runs, + %dump_test_schema_runs, + only_dump_test_table => 1, + role => 1, + section_pre_data => 1, + }, + unlike => { no_privs => 1, }, + }, + + + 'CREATE ACCESS METHOD regress_test_table_am' => { + create_order => 11, + create_sql => + 'CREATE ACCESS METHOD regress_table_am TYPE TABLE HANDLER heap_tableam_handler;', + regexp => qr/^ + \QCREATE ACCESS METHOD regress_table_am TYPE TABLE HANDLER heap_tableam_handler;\E + \n/xm, + like => { + %full_runs, section_pre_data => 1, + }, + }, + + # It's a bit tricky to ensure that the proper SET of default table + # AM occurs. To achieve that we create a table with the standard + # AM, test AM, standard AM. That guarantees that there needs to be + # a SET interspersed. Then use a regex that prevents interspersed + # SET ...; statements, followed by the expected CREATE TABLE. Not + # pretty, but seems hard to do better in this framework. + 'CREATE TABLE regress_pg_dump_table_am' => { + create_order => 12, + create_sql => ' + CREATE TABLE dump_test.regress_pg_dump_table_am_0() USING heap; + CREATE TABLE dump_test.regress_pg_dump_table_am_1 (col1 int) USING regress_table_am; + CREATE TABLE dump_test.regress_pg_dump_table_am_2() USING heap;', + regexp => qr/^ + \QSET default_table_access_method = regress_table_am;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_1 (\E + \n\s+\Qcol1 integer\E + \n\);/xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { exclude_dump_test_schema => 1 }, + }, + + 'CREATE MATERIALIZED VIEW regress_pg_dump_matview_am' => { + create_order => 13, + create_sql => ' + CREATE MATERIALIZED VIEW dump_test.regress_pg_dump_matview_am_0 USING heap AS SELECT 1; + CREATE MATERIALIZED VIEW dump_test.regress_pg_dump_matview_am_1 + USING regress_table_am AS SELECT count(*) FROM pg_class; + CREATE MATERIALIZED VIEW dump_test.regress_pg_dump_matview_am_2 USING heap AS SELECT 1;', + regexp => qr/^ + \QSET default_table_access_method = regress_table_am;\E + (\n(?!SET[^;]+;)[^\n]*)* + \QCREATE MATERIALIZED VIEW dump_test.regress_pg_dump_matview_am_1 AS\E + \n\s+\QSELECT count(*) AS count\E + \n\s+\QFROM pg_class\E + \n\s+\QWITH NO DATA;\E\n/xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { exclude_dump_test_schema => 1 }, + }); + +######################################### +# Create a PG instance to test actually dumping from + +my $node = get_new_node('main'); +$node->init; +$node->start; + +my $port = $node->port; + +# We need to see if this system supports CREATE COLLATION or not +# If it doesn't then we will skip all the COLLATION-related tests. +my $collation_support = 0; +my $collation_check_stderr; +$node->psql( + 'postgres', + "CREATE COLLATION testing FROM \"C\"; DROP COLLATION testing;", + on_error_stop => 0, + stderr => \$collation_check_stderr); + +if ($collation_check_stderr !~ /ERROR: /) +{ + $collation_support = 1; +} + +# Determine whether build supports LZ4. +my $supports_lz4 = check_pg_config("#define HAVE_LIBLZ4 1"); + +# Create a second database for certain tests to work against +$node->psql('postgres', 'create database regress_pg_dump_test;'); + +# Start with number of command_fails_like()*2 tests below (each +# command_fails_like is actually 2 tests) + number of command_ok()*3 +my $num_tests = 33; + +foreach my $run (sort keys %pgdump_runs) +{ + my $test_key = $run; + my $run_db = 'postgres'; + + if (defined($pgdump_runs{$run}->{database})) + { + $run_db = $pgdump_runs{$run}->{database}; + } + + # Each run of pg_dump is a test itself + $num_tests++; + + # If there is a restore cmd, that's another test + if ($pgdump_runs{$run}->{restore_cmd}) + { + $num_tests++; + } + + if ($pgdump_runs{$run}->{test_key}) + { + $test_key = $pgdump_runs{$run}->{test_key}; + } + + # Then count all the tests run against each run + foreach my $test (sort keys %tests) + { + + # postgres is the default database, if it isn't overridden + my $test_db = 'postgres'; + + # Specific tests can override the database to use + if (defined($tests{$test}->{database})) + { + $test_db = $tests{$test}->{database}; + } + + # The database to test against needs to match the database the run is + # for, so skip combinations where they don't match up. + if ($run_db ne $test_db) + { + next; + } + + # Skip any collation-related commands if there is no collation support + if (!$collation_support && defined($tests{$test}->{collation})) + { + next; + } + + # Skip tests specific to LZ4 if this build does not support + # this option. + if (!$supports_lz4 && defined($tests{$test}->{lz4})) + { + next; + } + + # If there is a like entry, but no unlike entry, then we will test the like case + if ($tests{$test}->{like}->{$test_key} + && !defined($tests{$test}->{unlike}->{$test_key})) + { + $num_tests++; + } + else + { + # We will test everything that isn't a 'like' + $num_tests++; + } + } +} +plan tests => $num_tests; + +######################################### +# Set up schemas, tables, etc, to be dumped. + +# Build up the create statements +my %create_sql = (); + +foreach my $test ( + sort { + if ($tests{$a}->{create_order} and $tests{$b}->{create_order}) + { + $tests{$a}->{create_order} <=> $tests{$b}->{create_order}; + } + elsif ($tests{$a}->{create_order}) + { + -1; + } + elsif ($tests{$b}->{create_order}) + { + 1; + } + else + { + 0; + } + } keys %tests) +{ + my $test_db = 'postgres'; + + if (defined($tests{$test}->{database})) + { + $test_db = $tests{$test}->{database}; + } + + if ($tests{$test}->{create_sql}) + { + + # Skip any collation-related commands if there is no collation support + if (!$collation_support && defined($tests{$test}->{collation})) + { + next; + } + + # Skip tests specific to LZ4 if this build does not support + # this option. + if (!$supports_lz4 && defined($tests{$test}->{lz4})) + { + next; + } + + # Add terminating semicolon + $create_sql{$test_db} .= $tests{$test}->{create_sql} . ";"; + } +} + +# Send the combined set of commands to psql +foreach my $db (sort keys %create_sql) +{ + $node->safe_psql($db, $create_sql{$db}); +} + +######################################### +# Test connecting to a non-existent database + +command_fails_like( + [ 'pg_dump', '-p', "$port", 'qqq' ], + qr/pg_dump: error: connection to server .* failed: FATAL: database "qqq" does not exist/, + 'connecting to a non-existent database'); + +######################################### +# Test connecting with an unprivileged user + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--role=regress_dump_test_role' ], + qr/\Qpg_dump: error: query failed: ERROR: permission denied for\E/, + 'connecting with an unprivileged user'); + +######################################### +# Test dumping a non-existent schema, table, and patterns with --strict-names + +command_fails_like( + [ 'pg_dump', '-p', "$port", '-n', 'nonexistent' ], + qr/\Qpg_dump: error: no matching schemas were found\E/, + 'dumping a non-existent schema'); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '-t', 'nonexistent' ], + qr/\Qpg_dump: error: no matching tables were found\E/, + 'dumping a non-existent table'); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--strict-names', '-n', 'nonexistent*' ], + qr/\Qpg_dump: error: no matching schemas were found for pattern\E/, + 'no matching schemas'); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--strict-names', '-t', 'nonexistent*' ], + qr/\Qpg_dump: error: no matching tables were found for pattern\E/, + 'no matching tables'); + +######################################### +# Test invalid multipart database names + +command_fails_like( + [ 'pg_dumpall', '-p', "$port", '--exclude-database', '.' ], + qr/pg_dumpall: error: improper qualified name \(too many dotted names\): \./, + 'pg_dumpall: option --exclude-database rejects multipart pattern "."' +); + +command_fails_like( + [ 'pg_dumpall', '-p', "$port", '--exclude-database', 'myhost.mydb' ], + qr/pg_dumpall: error: improper qualified name \(too many dotted names\): myhost\.mydb/, + 'pg_dumpall: option --exclude-database rejects multipart database names' +); + +######################################### +# Test valid database exclusion patterns + +$node->command_ok( + [ 'pg_dumpall', '-p', "$port", '--exclude-database', '"myhost.mydb"' ], + 'pg_dumpall: option --exclude-database handles database names with embedded dots' +); + +######################################### +# Test invalid multipart schema names + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--schema', 'myhost.mydb.myschema' ], + qr/pg_dump: error: improper qualified name \(too many dotted names\): myhost\.mydb\.myschema/, + 'pg_dump: option --schema rejects three-part schema names' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--schema', 'otherdb.myschema' ], + qr/pg_dump: error: cross-database references are not implemented: otherdb\.myschema/, + 'pg_dump: option --schema rejects cross-database multipart schema names' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--schema', '"some.other.db".myschema' ], + qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.myschema/, + 'pg_dump: option --schema rejects cross-database multipart schema names with embedded dots' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--schema', '.' ], + qr/pg_dump: error: cross-database references are not implemented: \./, + 'pg_dump: option --schema rejects degenerate two-part schema name: "."' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--schema', '..' ], + qr/pg_dump: error: improper qualified name \(too many dotted names\): \.\./, + 'pg_dump: option --schema rejects degenerate three-part schema name: ".."' +); + +######################################### +# Test invalid multipart relation names + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--table', 'myhost.mydb.myschema.mytable' ], + qr/pg_dump: error: improper relation name \(too many dotted names\): myhost\.mydb\.myschema\.mytable/, + 'pg_dump: option --table rejects four-part table names' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--table', 'otherdb.pg_catalog.pg_class' ], + qr/pg_dump: error: cross-database references are not implemented: otherdb\.pg_catalog\.pg_class/, + 'pg_dump: option --table rejects cross-database three part table names' +); + +command_fails_like( + [ 'pg_dump', '-p', "$port", '--table', '"some.other.db".pg_catalog.pg_class' ], + qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.pg_catalog\.pg_class/, + 'pg_dump: option --table rejects cross-database three part table names with embedded dots' +); + +######################################### +# Run all runs + +foreach my $run (sort keys %pgdump_runs) +{ + my $test_key = $run; + my $run_db = 'postgres'; + + $node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} }, + "$run: pg_dump runs"); + + if ($pgdump_runs{$run}->{restore_cmd}) + { + $node->command_ok(\@{ $pgdump_runs{$run}->{restore_cmd} }, + "$run: pg_restore runs"); + } + + if ($pgdump_runs{$run}->{test_key}) + { + $test_key = $pgdump_runs{$run}->{test_key}; + } + + my $output_file = slurp_file("$tempdir/${run}.sql"); + + ######################################### + # Run all tests where this run is included + # as either a 'like' or 'unlike' test. + + foreach my $test (sort keys %tests) + { + my $test_db = 'postgres'; + + if (defined($pgdump_runs{$run}->{database})) + { + $run_db = $pgdump_runs{$run}->{database}; + } + + if (defined($tests{$test}->{database})) + { + $test_db = $tests{$test}->{database}; + } + + # Skip any collation-related commands if there is no collation support + if (!$collation_support && defined($tests{$test}->{collation})) + { + next; + } + + # Skip tests specific to LZ4 if this build does not support + # this option. + if (!$supports_lz4 && defined($tests{$test}->{lz4})) + { + next; + } + + if ($run_db ne $test_db) + { + next; + } + + # Run the test listed as a like, unless it is specifically noted + # as an unlike (generally due to an explicit exclusion or similar). + if ($tests{$test}->{like}->{$test_key} + && !defined($tests{$test}->{unlike}->{$test_key})) + { + if (!ok($output_file =~ $tests{$test}->{regexp}, + "$run: should dump $test")) + { + diag("Review $run results in $tempdir"); + } + } + else + { + if (!ok($output_file !~ $tests{$test}->{regexp}, + "$run: should not dump $test")) + { + diag("Review $run results in $tempdir"); + } + } + } +} + +######################################### +# Stop the database instance, which will be removed at the end of the tests. + +$node->stop('fast'); diff --git a/src/bin/pg_dump/t/003_pg_dump_with_server.pl b/src/bin/pg_dump/t/003_pg_dump_with_server.pl new file mode 100644 index 0000000..f9fea9d --- /dev/null +++ b/src/bin/pg_dump/t/003_pg_dump_with_server.pl @@ -0,0 +1,39 @@ + +# Copyright (c) 2021, PostgreSQL Global Development Group + +use strict; +use warnings; + +use PostgresNode; +use TestLib; +use Test::More tests => 3; + +my $tempdir = TestLib::tempdir; +my $tempdir_short = TestLib::tempdir_short; + +my $node = get_new_node('main'); +my $port = $node->port; + +$node->init; +$node->start; + +######################################### +# Verify that dumping foreign data includes only foreign tables of +# matching servers + +$node->safe_psql('postgres', "CREATE FOREIGN DATA WRAPPER dummy"); +$node->safe_psql('postgres', "CREATE SERVER s0 FOREIGN DATA WRAPPER dummy"); +$node->safe_psql('postgres', "CREATE SERVER s1 FOREIGN DATA WRAPPER dummy"); +$node->safe_psql('postgres', "CREATE SERVER s2 FOREIGN DATA WRAPPER dummy"); +$node->safe_psql('postgres', "CREATE FOREIGN TABLE t0 (a int) SERVER s0"); +$node->safe_psql('postgres', "CREATE FOREIGN TABLE t1 (a int) SERVER s1"); +my ($cmd, $stdout, $stderr, $result); + +command_fails_like( + [ "pg_dump", '-p', $port, '--include-foreign-data=s0', 'postgres' ], + qr/foreign-data wrapper \"dummy\" has no handler\r?\npg_dump: error: query was:.*t0/, + "correctly fails to dump a foreign table from a dummy FDW"); + +command_ok( + [ "pg_dump", '-p', $port, '-a', '--include-foreign-data=s2', 'postgres' ], + "dump foreign server with no tables"); diff --git a/src/bin/pg_dump/t/010_dump_connstr.pl b/src/bin/pg_dump/t/010_dump_connstr.pl new file mode 100644 index 0000000..6478894 --- /dev/null +++ b/src/bin/pg_dump/t/010_dump_connstr.pl @@ -0,0 +1,231 @@ + +# Copyright (c) 2021, PostgreSQL Global Development Group + +use strict; +use warnings; + +use PostgresNode; +use TestLib; +use Test::More; + +if ($TestLib::is_msys2) +{ + plan skip_all => 'High bit name tests fail on Msys2'; +} +else +{ + plan tests => 14; +} + +# We're going to use byte sequences that aren't valid UTF-8 strings. Use +# LATIN1, which accepts any byte and has a conversion from each byte to UTF-8. +$ENV{LC_ALL} = 'C'; +$ENV{PGCLIENTENCODING} = 'LATIN1'; + +# Create database and user names covering the range of LATIN1 +# characters, for use in a connection string by pg_dumpall. Skip ',' +# because of pg_regress --create-role, skip [\n\r] because pg_dumpall +# does not allow them. We also skip many ASCII letters, to keep the +# total number of tested characters to what will fit in four names. +# The odds of finding something interesting by testing all ASCII letters +# seem too small to justify the cycles of testing a fifth name. +my $dbname1 = + 'regression' + . generate_ascii_string(1, 9) + . generate_ascii_string(11, 12) + . generate_ascii_string(14, 33) + . ($TestLib::windows_os ? '' : '"x"') # IPC::Run mishandles '"' on Windows + . generate_ascii_string(35, 43) # skip ',' + . generate_ascii_string(45, 54); +my $dbname2 = 'regression' . generate_ascii_string(55, 65) # skip 'B'-'W' + . generate_ascii_string(88, 99) # skip 'd'-'w' + . generate_ascii_string(120, 149); +my $dbname3 = 'regression' . generate_ascii_string(150, 202); +my $dbname4 = 'regression' . generate_ascii_string(203, 255); + +(my $username1 = $dbname1) =~ s/^regression/regress_/; +(my $username2 = $dbname2) =~ s/^regression/regress_/; +(my $username3 = $dbname3) =~ s/^regression/regress_/; +(my $username4 = $dbname4) =~ s/^regression/regress_/; + +my $src_bootstrap_super = 'regress_postgres'; +my $dst_bootstrap_super = 'boot'; + +my $node = get_new_node('main'); +$node->init(extra => + [ '-U', $src_bootstrap_super, '--locale=C', '--encoding=LATIN1' ]); + +# prep pg_hba.conf and pg_ident.conf +$node->run_log( + [ + $ENV{PG_REGRESS}, '--config-auth', + $node->data_dir, '--user', + $src_bootstrap_super, '--create-role', + "$username1,$username2,$username3,$username4" + ]); +$node->start; + +my $backupdir = $node->backup_dir; +my $discard = "$backupdir/discard.sql"; +my $plain = "$backupdir/plain.sql"; +my $dirfmt = "$backupdir/dirfmt"; + +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname1 ]); +$node->run_log( + [ 'createuser', '-U', $src_bootstrap_super, '-s', $username1 ]); +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname2 ]); +$node->run_log( + [ 'createuser', '-U', $src_bootstrap_super, '-s', $username2 ]); +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname3 ]); +$node->run_log( + [ 'createuser', '-U', $src_bootstrap_super, '-s', $username3 ]); +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname4 ]); +$node->run_log( + [ 'createuser', '-U', $src_bootstrap_super, '-s', $username4 ]); + + +# For these tests, pg_dumpall -r is used because it produces a short +# dump. +$node->command_ok( + [ + 'pg_dumpall', '-r', '-f', $discard, '--dbname', + $node->connstr($dbname1), + '-U', $username4 + ], + 'pg_dumpall with long ASCII name 1'); +$node->command_ok( + [ + 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', + $node->connstr($dbname2), + '-U', $username3 + ], + 'pg_dumpall with long ASCII name 2'); +$node->command_ok( + [ + 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', + $node->connstr($dbname3), + '-U', $username2 + ], + 'pg_dumpall with long ASCII name 3'); +$node->command_ok( + [ + 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', + $node->connstr($dbname4), + '-U', $username1 + ], + 'pg_dumpall with long ASCII name 4'); +$node->command_ok( + [ + 'pg_dumpall', '-U', + $src_bootstrap_super, '--no-sync', + '-r', '-l', + 'dbname=template1' + ], + 'pg_dumpall -l accepts connection string'); + +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, "foo\n\rbar" ]); + +# not sufficient to use -r here +$node->command_fails( + [ 'pg_dumpall', '-U', $src_bootstrap_super, '--no-sync', '-f', $discard ], + 'pg_dumpall with \n\r in database name'); +$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, "foo\n\rbar" ]); + + +# make a table, so the parallel worker has something to dump +$node->safe_psql( + $dbname1, + 'CREATE TABLE t0()', + extra_params => [ '-U', $src_bootstrap_super ]); + +# XXX no printed message when this fails, just SIGPIPE termination +$node->command_ok( + [ + 'pg_dump', '-Fd', '--no-sync', '-j2', '-f', $dirfmt, '-U', $username1, + $node->connstr($dbname1) + ], + 'parallel dump'); + +# recreate $dbname1 for restore test +$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, $dbname1 ]); +$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname1 ]); + +$node->command_ok( + [ + 'pg_restore', '-v', '-d', 'template1', + '-j2', '-U', $username1, $dirfmt + ], + 'parallel restore'); + +$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, $dbname1 ]); + +$node->command_ok( + [ + 'pg_restore', '-C', '-v', '-d', + 'template1', '-j2', '-U', $username1, + $dirfmt + ], + 'parallel restore with create'); + + +$node->command_ok( + [ 'pg_dumpall', '--no-sync', '-f', $plain, '-U', $username1 ], + 'take full dump'); +system_log('cat', $plain); +my ($stderr, $result); +my $restore_super = qq{regress_a'b\\c=d\\ne"f}; +$restore_super =~ s/"//g + if $TestLib::windows_os; # IPC::Run mishandles '"' on Windows + + +# Restore full dump through psql using environment variables for +# dbname/user connection parameters + +my $envar_node = get_new_node('destination_envar'); +$envar_node->init( + extra => + [ '-U', $dst_bootstrap_super, '--locale=C', '--encoding=LATIN1' ], + auth_extra => + [ '--user', $dst_bootstrap_super, '--create-role', $restore_super ]); +$envar_node->start; + +# make superuser for restore +$envar_node->run_log( + [ 'createuser', '-U', $dst_bootstrap_super, '-s', $restore_super ]); + +{ + local $ENV{PGPORT} = $envar_node->port; + local $ENV{PGUSER} = $restore_super; + $result = run_log([ 'psql', '-X', '-f', $plain ], '2>', \$stderr); +} +ok($result, + 'restore full dump using environment variables for connection parameters' +); +is($stderr, '', 'no dump errors'); + + +# Restore full dump through psql using command-line options for +# dbname/user connection parameters. "\connect dbname=" forgets +# user/port from command line. + +my $cmdline_node = get_new_node('destination_cmdline'); +$cmdline_node->init( + extra => + [ '-U', $dst_bootstrap_super, '--locale=C', '--encoding=LATIN1' ], + auth_extra => + [ '--user', $dst_bootstrap_super, '--create-role', $restore_super ]); +$cmdline_node->start; +$cmdline_node->run_log( + [ 'createuser', '-U', $dst_bootstrap_super, '-s', $restore_super ]); +{ + $result = run_log( + [ + 'psql', '-p', $cmdline_node->port, '-U', + $restore_super, '-X', '-f', $plain + ], + '2>', + \$stderr); +} +ok($result, + 'restore full dump with command-line options for connection parameters'); +is($stderr, '', 'no dump errors'); -- cgit v1.2.3