diff --git a/README.md b/README.md index 7523403..05dab20 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ happened, not just whether pg_restore was noisy. > [!NOTE] > Pre-1.0. The pipeline works end to end (live wrapper, error classification, -> exit-code normalization); an honest ETA is still to come. +> exit-code normalization, stdin restores); an honest ETA is still to come. ## Install @@ -83,7 +83,8 @@ ele --replay # replay a captured stderr log through the live view ``` `--plan` and `--replay` are offline: they never connect to a database. For both, -`` is either a dump or a saved `pg_restore -l` listing (see below). +`` is either a dump or a saved `pg_restore -l` listing (see below); +`--replay` also takes `-`, meaning no plan at all. `--replay` is the safe dry-run. Feed it a captured stderr log and a plan, and it reruns the whole pipeline: on a terminal it drives the real live block (progress, @@ -96,11 +97,26 @@ Saving the listing once lets you dry-run (or re-`--plan`) without the dump on ha ```sh pg_restore -l latest.dump > latest.toc # capture the plan once (no database) ele --replay latest.toc ele-20260719.log # replay any captured log against it +ele --replay - ele-20260719.log # replay with no plan: the countless view ``` Tune the animation length with `ELE_REPLAY_SECONDS` (default 12; `0` feeds instantly and just prints the summary). +### Restoring from stdin + +```sh +cat latest.dump | ele -d myapp_dev --clean --no-owner +``` + +Preflight needs a file it can open, so a dump arriving on a pipe has no table of +contents and no per-phase totals. `ele` still runs the whole view: spinner, +current-object line, grouped errors, summary and exit code, with a per-phase +object count in place of each bar. Percentages and the skipped-object count are +gone, because both need a total. + +`ele --replay - ` shows the same view offline, against a captured log. + ## How It Works - **Preflight** runs `pg_restore -l` (under `LC_ALL=C`) and parses the table of @@ -115,7 +131,10 @@ instantly and just prints the summary). through untouched. - **Parse & aggregate** turn that stream into progress and grouped errors, surviving the way parallel (`-j`) workers interleave their output. Errors are - fingerprinted (quoted identifiers blanked) and classified benign or real. + fingerprinted (quoted identifiers blanked) and classified benign or real. The + table of message wordings the parser matches on is generated from PostgreSQL's + own `pg_dump` message catalogs (`just gen-messages`), across release tags 13 + to 18, so a new major is a regeneration rather than a rewrite. - **Exit code** is normalized: if every error was benign, `ele` exits `0` with a note; any real error exits nonzero. Set `ELE_STRICT_EXIT=1` to keep pg_restore's raw code. @@ -127,12 +146,16 @@ collision with pg_restore's own flag surface. | Variable | Effect | |---|---| +| `ELE_LOG=path` | Write the raw log here instead of `./ele-.log`. `/dev/null` discards it. | | `ELE_STRICT_EXIT=1` | Don't normalize the exit code; return pg_restore's own. | | `NO_COLOR=1` | Disable color. | | `ELE_PLAIN=1` | Disable the repaint block; emit periodic one-line progress instead. | +| `ELE_PASSTHROUGH=1` | Don't wrap at all: raw `pg_restore` output and its own exit code. | `ele` also drops to plain output automatically when stderr isn't a terminal, or -under `CI` / `CLAUDECODE`. +under `CI` / `CLAUDECODE`. Plain output is still the aggregated view - a summary +and periodic progress, never the firehose. `ELE_PASSTHROUGH=1` is the only way +back to raw `pg_restore`. ## Feedback diff --git a/cmd/ele/main.go b/cmd/ele/main.go index de3abcd..dee7cc4 100644 --- a/cmd/ele/main.go +++ b/cmd/ele/main.go @@ -72,7 +72,8 @@ func printUsage(w io.Writer) { " ele --plan print the parsed restore plan and exit\n"+ " ele --replay dry-run: replay a captured stderr log through the\n"+ " live view\n"+ - " ( is a dump or a saved pg_restore -l listing)\n") + " ( is a dump or a saved pg_restore -l listing;\n"+ + " '-' replays with no plan, as a stdin restore runs)\n") } func preflightOnly(out io.Writer, dumpPath string) error { diff --git a/internal/aggregator/aggregator.go b/internal/aggregator/aggregator.go index f2cfdc2..0e337d0 100644 --- a/internal/aggregator/aggregator.go +++ b/internal/aggregator/aggregator.go @@ -26,6 +26,11 @@ type Aggregator struct { cfg Config now func() time.Time // injectable clock for item timing + // countless: no plan, so no denominators. Phases are still counted - the + // event's own description gives the section - they just have no total to + // count against. This is the stdin restore, where preflight is impossible. + countless bool + // phase denominators, from the plan total map[toc.Section]int // phase progress @@ -70,31 +75,35 @@ type inflightItem struct { start time.Time } -// New builds an Aggregator for a restore plan and config. +// New builds an Aggregator for a restore plan and config. A nil plan is the +// countless restore: everything still aggregates, only the denominators are +// missing. func New(plan *toc.RestorePlan, cfg Config) *Aggregator { - pre, data, post, _ := plan.PhaseCounts() - bytesTotal, byteSized := plan.DataBytes(), false - // DataBytes is only meaningful when preflight sized every data file; the - // caller signals that via a nonzero total together with ByteSized. Here we - // treat any positive total as byte-capable and let the renderer decide. - if bytesTotal > 0 { - byteSized = true - } - return &Aggregator{ - plan: plan, - cfg: cfg, - now: time.Now, - total: map[toc.Section]int{ - toc.PreData: pre, toc.Data: data, toc.PostData: post, - }, + a := &Aggregator{ + plan: plan, + cfg: cfg, + now: time.Now, + countless: plan == nil, + total: map[toc.Section]int{}, done: map[toc.Section]int{}, sectionDone: map[toc.Section]bool{}, doneIDs: map[int]bool{}, - bytesTotal: bytesTotal, - byteSized: byteSized, inflight: map[int]*inflightItem{}, groups: map[string]*errorGroup{}, } + if plan == nil { + return a + } + + pre, data, post, _ := plan.PhaseCounts() + a.total = map[toc.Section]int{toc.PreData: pre, toc.Data: data, toc.PostData: post} + // DataBytes is only meaningful when preflight sized every data file; the + // caller signals that via a nonzero total together with ByteSized. Here we + // treat any positive total as byte-capable and let the renderer decide. + if bytesTotal := plan.DataBytes(); bytesTotal > 0 { + a.bytesTotal, a.byteSized = bytesTotal, true + } + return a } // Feed folds one event into the running state. @@ -102,7 +111,7 @@ func (a *Aggregator) Feed(ev parser.Event) { switch ev.Kind { case parser.KindProcessingItem: a.parallel = true - a.completeID(ev.DumpID) + a.completeID(ev.DumpID, ev.Desc) case parser.KindLaunchItem: a.parallel = true @@ -116,7 +125,7 @@ func (a *Aggregator) Feed(ev parser.Event) { }) delete(a.inflight, ev.DumpID) } - a.completeID(ev.DumpID) + a.completeID(ev.DumpID, ev.Desc) case parser.KindCreating: if !a.parallel { @@ -152,20 +161,35 @@ func (a *Aggregator) Feed(ev parser.Event) { } // completeID marks the entry with the given dump id done, once. Its phase and -// byte size come from the plan. Ids not in the plan are ignored. -func (a *Aggregator) completeID(id int) { +// byte size come from the plan; ids the plan doesn't know are ignored, since a +// real plan is the authority on what this restore contains. +// +// Countless mode has no plan to consult, so the event's own description carries +// the phase instead - toc.SectionOf maps it exactly the way the plan would have. +// Sizes stay unknown either way: only preflight can stat a data file. +func (a *Aggregator) completeID(id int, desc string) { if a.doneIDs[id] { return } - e, ok := a.plan.Get(id) - if !ok { + if a.plan != nil { + e, ok := a.plan.Get(id) + if !ok { + return + } + a.doneIDs[id] = true + a.incPhase(e.Section) + if e.Section == toc.Data && e.HasBytes { + a.bytesDone += e.Bytes + } + return + } + + s := toc.SectionOf(desc) + if s == toc.SectionUnknown { return } a.doneIDs[id] = true - a.incPhase(e.Section) - if e.Section == toc.Data && e.HasBytes { - a.bytesDone += e.Bytes - } + a.incPhase(s) } // completeSerial advances a phase in serial mode, where events carry no dump id @@ -204,10 +228,11 @@ func (a *Aggregator) setCurrent(desc, name string) { // incPhase increments a phase's done count, capped at its total so a stray // double-count can never push a bar past 100%. The first real completion also -// ends the DROP wave. +// ends the DROP wave. Countless mode has no total to cap against - and nothing +// to overflow, since it draws counts rather than bars. func (a *Aggregator) incPhase(s toc.Section) { a.dropWaveOver = true - if a.done[s] < a.total[s] { + if a.countless || a.done[s] < a.total[s] { a.done[s]++ } } diff --git a/internal/aggregator/aggregator_test.go b/internal/aggregator/aggregator_test.go index 321812f..9b245fe 100644 --- a/internal/aggregator/aggregator_test.go +++ b/internal/aggregator/aggregator_test.go @@ -29,6 +29,18 @@ func loadPlan(t *testing.T) *toc.RestorePlan { // replay drives a captured stderr fixture (from the parser package's testdata) // through parser then aggregator, exactly as the runner will wire them. func replay(t *testing.T, fixture string, cfg Config) *Aggregator { + t.Helper() + return feed(t, New(loadPlan(t), cfg), fixture) +} + +// replayCountless drives the same fixture with no plan - the stdin restore, +// where preflight is impossible and only numerators exist. +func replayCountless(t *testing.T, fixture string, cfg Config) *Aggregator { + t.Helper() + return feed(t, New(nil, cfg), fixture) +} + +func feed(t *testing.T, agg *Aggregator, fixture string) *Aggregator { t.Helper() f, err := os.Open(filepath.Join("..", "parser", "testdata", fixture)) if err != nil { @@ -36,7 +48,6 @@ func replay(t *testing.T, fixture string, cfg Config) *Aggregator { } defer f.Close() - agg := New(loadPlan(t), cfg) p := parser.New() sc := bufio.NewScanner(f) sc.Buffer(make([]byte, 0, 64*1024), 4*1024*1024) @@ -321,3 +332,60 @@ func TestClassifyBenign(t *testing.T) { t.Error("unique violation must be real") } } + +// TestCountlessSerial is the stdin restore: no plan, so no denominators, but +// every phase still counts and the error groups are unchanged. Counts come from +// each event's own object description rather than a TOC lookup. +func TestCountlessSerial(t *testing.T) { + cfg := Config{Clean: true, NoOwner: true} + s := replayCountless(t, "clean-serial.stderr", cfg).Snapshot() + planned := replay(t, "clean-serial.stderr", cfg).Snapshot() + + if !s.Countless { + t.Error("Countless = false, want true for a nil plan") + } + for _, p := range []PhaseProgress{s.Pre, s.Data, s.Post} { + if p.Total != 0 { + t.Errorf("%s total = %d, want 0 (no plan to count against)", p.Section, p.Total) + } + if p.Done == 0 { + t.Errorf("%s made no progress", p.Section) + } + } + if s.ByteSized { + t.Error("ByteSized = true; only preflight can size data files") + } + + // The planned run caps each phase at its denominator, so countless counting + // can match it but never fall behind it. + if s.Pre.Done < planned.Pre.Done || s.Data.Done < planned.Data.Done || s.Post.Done < planned.Post.Done { + t.Errorf("countless %d/%d/%d behind planned %d/%d/%d", + s.Pre.Done, s.Data.Done, s.Post.Done, + planned.Pre.Done, planned.Data.Done, planned.Post.Done) + } + + // Error classification never depended on the plan. + if s.ErrTotal != planned.ErrTotal || s.ErrBenign != planned.ErrBenign || s.ErrReal != planned.ErrReal { + t.Errorf("errors = %d/%d/%d, want the planned run's %d/%d/%d", + s.ErrTotal, s.ErrBenign, s.ErrReal, + planned.ErrTotal, planned.ErrBenign, planned.ErrReal) + } +} + +// TestCountlessParallel confirms the -j path counts too: item events carry the +// object description alongside the dump id, so a missing plan costs only the +// denominators - in-flight tracking and timings are unaffected. +func TestCountlessParallel(t *testing.T) { + agg := replayCountless(t, "clean-j4.stderr", Config{Clean: true, NoOwner: true}) + s := agg.Snapshot() + + if s.Data.Done == 0 || s.Post.Done == 0 { + t.Errorf("data %d, post %d: want both counted", s.Data.Done, s.Post.Done) + } + if len(s.InFlight) != 0 { + t.Errorf("in-flight not drained: %+v", s.InFlight) + } + if len(s.Slowest) == 0 { + t.Error("no item timings; launching/finished pairs should still time") + } +} diff --git a/internal/aggregator/snapshot.go b/internal/aggregator/snapshot.go index d67d162..ce57fe0 100644 --- a/internal/aggregator/snapshot.go +++ b/internal/aggregator/snapshot.go @@ -59,6 +59,11 @@ type Snapshot struct { Data PhaseProgress Post PhaseProgress + // Countless: the restore ran without a plan (a dump on stdin), so every + // Total is 0 and the phases carry counts only. The renderer drops the bars + // rather than drawing three empty tracks. + Countless bool + ByteSized bool BytesDone int64 BytesTotal int64 @@ -101,6 +106,7 @@ func (a *Aggregator) Snapshot() Snapshot { Pre: a.phase(toc.PreData), Data: a.phase(toc.Data), Post: a.phase(toc.PostData), + Countless: a.countless, ByteSized: a.byteSized, BytesDone: a.bytesDone, BytesTotal: a.bytesTotal, diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 5bf5f1e..e0329b3 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -36,6 +36,12 @@ var spinner = []rune("⣾⣽⣻⢿⡿⣟⣯⣷") // code ele should exit with. stdout receives the child's stdout untouched; // stderrFile is the terminal channel for the status block and summary. func Run(ctx context.Context, args []string, stdout io.Writer, stderrFile *os.File) (int, error) { + // ELE_PASSTHROUGH is the opt-out: the user wants pg_restore exactly as it + // comes, so it wins over every mode below. + if passthroughRequested() { + return passthrough(ctx, args, stdout, stderrFile) + } + f := detectFlags(args) // Not a restore-to-database (no -d): ele adds nothing, so pass through. @@ -47,18 +53,21 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderrFile *os.Fi _, err := os.Stat(p) return err == nil }) + // No plan (a dump arriving on stdin, or a preflight that failed) means no + // denominators - but the aggregation, the working line and the error panel + // don't need them. Run countless rather than drop the user back into the + // firehose; only ELE_PASSTHROUGH does that. plan := preflightPlan(ctx, dumpPath, stderrFile) + title := f.dbName if plan == nil { - // No plan means no denominators; fall back to a transparent run rather - // than draw meaningless bars. - fmt.Fprintln(stderrFile, "ele: no restore plan available; passing through") - return passthrough(ctx, args, stdout, stderrFile) + fmt.Fprintln(stderrFile, "ele: "+countlessReason(dumpPath)+"; progress runs without totals") + title += " (no totals)" } - logPath := "ele-" + time.Now().Format("20060102-150405") + ".log" + logPath := logDestination(time.Now()) logf, err := os.Create(logPath) if err != nil { - return 1, fmt.Errorf("creating log: %w", err) + return 1, fmt.Errorf("creating log %s: %w", logPath, err) } defer logf.Close() @@ -68,7 +77,7 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderrFile *os.Fi start := time.Now() live, stopTicker := startRenderer(stderrFile, agg, &mu, start, render.Opts{ - Title: f.dbName, + Title: title, LogPath: logPath, Styles: render.NewStyles(stderrFile), }) @@ -180,6 +189,16 @@ func blockSize(stderrFile *os.File) (width, maxLines int) { return w, 0 } +// countlessReason names why this run has no denominators, for the note printed +// above the block. A missing dump path is the stdin case the contract calls out; +// anything else means preflight itself failed, and it already said how. +func countlessReason(dumpPath string) string { + if dumpPath == "" { + return "no dump to preflight (restoring from stdin)" + } + return "preflight produced no plan" +} + // preflightPlan runs preflight, returning nil (with a note) when it can't. func preflightPlan(ctx context.Context, dumpPath string, stderrFile *os.File) *toc.RestorePlan { if dumpPath == "" { @@ -198,7 +217,7 @@ func preflightPlan(ctx context.Context, dumpPath string, stderrFile *os.File) *t // hack. A signal death or any real error keeps a failing code. func exitCode(result *runner.Result, snap aggregator.Snapshot, stderrFile *os.File) int { code := result.ExitCode - if code != 0 && !result.Signaled && snap.ErrReal == 0 && os.Getenv("ELE_STRICT_EXIT") == "" { + if code != 0 && !result.Signaled && snap.ErrReal == 0 && !strictExit() { fmt.Fprintf(stderrFile, "\nele: pg_restore exited %d but all errors were benign; normalizing to 0\n", code) return 0 } diff --git a/internal/engine/env.go b/internal/engine/env.go new file mode 100644 index 0000000..dd3c17c --- /dev/null +++ b/internal/engine/env.go @@ -0,0 +1,34 @@ +package engine + +import ( + "os" + "time" +) + +// ele has no flags of its own - pg_restore owns the whole argv - so every knob +// is an environment variable. These three are the engine's; the renderer reads +// ELE_PLAIN / NO_COLOR / CI / CLAUDECODE in internal/render, and --replay reads +// ELE_REPLAY_SECONDS. Unset and empty always mean the same thing. +const ( + envLog = "ELE_LOG" + envPassthrough = "ELE_PASSTHROUGH" + envStrictExit = "ELE_STRICT_EXIT" +) + +// logDestination is where the raw pg_restore stderr gets teed: ELE_LOG when it +// names a path, else a timestamped file in the working directory. +func logDestination(now time.Time) string { + if p := os.Getenv(envLog); p != "" { + return p + } + return "ele-" + now.Format("20060102-150405") + ".log" +} + +// passthroughRequested reports whether ELE_PASSTHROUGH asks for the raw +// firehose - pg_restore's own stderr and exit code, no aggregation. It is the +// only way back to unwrapped output; the degraded modes never give it. +func passthroughRequested() bool { return os.Getenv(envPassthrough) != "" } + +// strictExit reports whether ELE_STRICT_EXIT asks for pg_restore's raw exit +// code, leaving a benign-only failure nonzero. +func strictExit() bool { return os.Getenv(envStrictExit) != "" } diff --git a/internal/engine/env_test.go b/internal/engine/env_test.go new file mode 100644 index 0000000..cba26bb --- /dev/null +++ b/internal/engine/env_test.go @@ -0,0 +1,51 @@ +package engine + +import ( + "strings" + "testing" + "time" +) + +func TestLogDestination(t *testing.T) { + at := time.Date(2026, 7, 22, 16, 18, 15, 0, time.UTC) + + t.Run("default is timestamped in the cwd", func(t *testing.T) { + t.Setenv(envLog, "") + if got := logDestination(at); got != "ele-20260722-161815.log" { + t.Errorf("logDestination = %q, want the timestamped default", got) + } + }) + + t.Run("ELE_LOG names the path", func(t *testing.T) { + t.Setenv(envLog, "/tmp/restore.log") + if got := logDestination(at); got != "/tmp/restore.log" { + t.Errorf("logDestination = %q, want /tmp/restore.log", got) + } + }) + + // Empty has to behave as unset, the way every other var here does. + t.Run("empty falls back to the default", func(t *testing.T) { + t.Setenv(envLog, "") + if got := logDestination(at); !strings.HasPrefix(got, "ele-") { + t.Errorf("logDestination = %q, want the default", got) + } + }) +} + +func TestEnvFlags(t *testing.T) { + t.Run("unset", func(t *testing.T) { + t.Setenv(envPassthrough, "") + t.Setenv(envStrictExit, "") + if passthroughRequested() || strictExit() { + t.Error("flags set with empty environment") + } + }) + + t.Run("set", func(t *testing.T) { + t.Setenv(envPassthrough, "1") + t.Setenv(envStrictExit, "1") + if !passthroughRequested() || !strictExit() { + t.Error("flags not picked up") + } + }) +} diff --git a/internal/engine/replay.go b/internal/engine/replay.go index 1f46c3e..283101e 100644 --- a/internal/engine/replay.go +++ b/internal/engine/replay.go @@ -24,7 +24,8 @@ const replaySeconds = 12 // Replay reruns a captured pg_restore stderr log through the full pipeline // without touching a database - a safe dry-run of the live view. planSource is -// either a real dump (preflighted) or a saved `pg_restore -l` listing file; +// a real dump (preflighted), a saved `pg_restore -l` listing file, or "-" for +// the countless view a planless restore gets; // logPath is the captured stderr. On a TTY it drives the live block paced over // replaySeconds, then prints the summary; otherwise it prints milestones and the // summary. The exit code reflects the log's verdict: real errors -> 1, else 0. @@ -43,9 +44,14 @@ func Replay(ctx context.Context, planSource, logPath string, stdout io.Writer, s p := parser.New() var mu sync.Mutex + title := "(replay) " + logPath + if plan == nil { + title += " (no totals)" + } + start := time.Now() live, stopTicker := startRenderer(stderrFile, agg, &mu, start, render.Opts{ - Title: "(replay) " + logPath, + Title: title, LogPath: logPath, Styles: render.NewStyles(stderrFile), }) @@ -112,8 +118,13 @@ func replayPacing(live bool, lines int) time.Duration { } // loadPlan builds a RestorePlan from a dump or a saved `pg_restore -l` listing. -// preflight.Run handles the detection for both. +// preflight.Run handles the detection for both. "-" means no plan at all: the +// countless replay, which is how the denominator-free view a stdin restore gets +// can be seen and tested without a stdin restore. func loadPlan(ctx context.Context, source string) (*toc.RestorePlan, error) { + if source == "-" { + return nil, nil + } res, err := preflight.Run(ctx, source) if err != nil { return nil, err diff --git a/internal/engine/replay_test.go b/internal/engine/replay_test.go index 3ca58b8..9d62cc7 100644 --- a/internal/engine/replay_test.go +++ b/internal/engine/replay_test.go @@ -74,3 +74,31 @@ func TestLoadPlanListing(t *testing.T) { t.Errorf("phase counts = %d/%d/%d, want 15/7/11", pre, data, post) } } + +// TestReplayCountless is the offline view of a stdin restore: "-" for the plan +// means no denominators at all. The same log still yields counts, the same +// benign verdict, and exit 0 - only the bars are gone. +func TestReplayCountless(t *testing.T) { + out, code := runReplay(t, "-", logFixture) + if code != 0 { + t.Errorf("exit = %d, want 0 (all errors benign)", code) + } + for _, want := range []string{"success", "21 benign", "objects"} { + if !strings.Contains(out, want) { + t.Errorf("countless summary missing %q:\n%s", want, out) + } + } + for _, unwanted := range []string{"15/15", "7/7", "11/11"} { + if strings.Contains(out, unwanted) { + t.Errorf("countless summary shows the planned fraction %q:\n%s", unwanted, out) + } + } +} + +// A nil plan is the contract loadPlan owes Replay for "-", not an error. +func TestLoadPlanCountless(t *testing.T) { + plan, err := loadPlan(context.Background(), "-") + if err != nil || plan != nil { + t.Errorf("loadPlan(\"-\") = %v, %v; want nil, nil", plan, err) + } +} diff --git a/internal/parser/messages.go b/internal/parser/messages.go new file mode 100644 index 0000000..4e23f79 --- /dev/null +++ b/internal/parser/messages.go @@ -0,0 +1,49 @@ +package parser + +import "strings" + +// A message body is matched against a table generated from pg_dump's own +// gettext catalogs - see tools/pgmsg and messages_gen.go. This file is the +// hand-written half of that split: what a matched message means, and which +// Event fields its arguments fill. Wording lives upstream; meaning lives here. + +// shape is how a message's format arguments are read back out of the printed +// line. Each shape is named for the Event fields it fills. +type shape uint8 + +const ( + shapeNone shape = iota // no arguments worth keeping + shapeTOCEntry // a TOC listing line; sets the error-context dump id + shapeDescTag // " " -> Desc, Tag + shapeDescName // " " -> Desc, Name + shapeDescQuoted // ` ""` -> Desc, Name + shapeQuotedName // `""` -> Name + shapeItem // " " -> DumpID, Desc, Tag +) + +// message is one row of the generated table: the text pg_restore prints before +// its first argument, and what that message means. +type message struct { + literal string + exact bool // the whole message is literal - it takes no arguments + kind Kind + shape shape +} + +// matchMessage finds the message whose literal opens body and returns it with +// the remainder: the arguments pg_restore filled in. The table is ordered +// longest-literal-first, so the first hit is the most specific one. +func matchMessage(body string) (message, string, bool) { + for _, m := range messages { + if m.exact { + if body == m.literal { + return m, "", true + } + continue + } + if strings.HasPrefix(body, m.literal) { + return m, body[len(m.literal):], true + } + } + return message{}, "", false +} diff --git a/internal/parser/messages_gen.go b/internal/parser/messages_gen.go new file mode 100644 index 0000000..2a76c7b --- /dev/null +++ b/internal/parser/messages_gen.go @@ -0,0 +1,39 @@ +// Code generated by tools/pgmsg. DO NOT EDIT. +// +// Source: src/bin/pg_dump/po/{de,fr}.po at REL_13_STABLE .. REL_18_STABLE +// (github.com/postgres/postgres). Regenerate with `just gen-messages`. + +package parser + +// messages is what pg_restore prints, mapped to what it means. Ordered +// longest-literal-first, so the first match is the most specific one. +var messages = []message{ + // "connecting to database for restore" (13-18) + {literal: "connecting to database for restore", exact: true, kind: KindInfo, shape: shapeNone}, + // "entering main parallel loop" (13-18) + {literal: "entering main parallel loop", exact: true, kind: KindInfo, shape: shapeNone}, + // "finished main parallel loop" (13-18) + {literal: "finished main parallel loop", exact: true, kind: KindInfo, shape: shapeNone}, + // "processing data for table \"%s.%s\"" (13-18) + {literal: "processing data for table ", exact: false, kind: KindProcessingData, shape: shapeQuotedName}, + // "while PROCESSING TOC:" (13-18) + {literal: "while PROCESSING TOC:", exact: true, kind: KindInfo, shape: shapeNone}, + // "while INITIALIZING:" (13-18) + {literal: "while INITIALIZING:", exact: true, kind: KindInfo, shape: shapeNone}, + // "while FINALIZING:" (13-18) + {literal: "while FINALIZING:", exact: true, kind: KindInfo, shape: shapeNone}, + // "processing item %d %s %s" (13-18) + {literal: "processing item ", exact: false, kind: KindProcessingItem, shape: shapeItem}, + // "from TOC entry %d; %u %u %s %s %s" (13-18) + {literal: "from TOC entry ", exact: false, kind: KindUnknown, shape: shapeTOCEntry}, + // "launching item %d %s %s" (13-18) + {literal: "launching item ", exact: false, kind: KindLaunchItem, shape: shapeItem}, + // "finished item %d %s %s" (13-18) + {literal: "finished item ", exact: false, kind: KindFinishItem, shape: shapeItem}, + // "executing %s %s" (13-18), "executing %s" (13-18) + {literal: "executing ", exact: false, kind: KindExecuting, shape: shapeDescName}, + // "creating %s \"%s.%s\"" (13-18), "creating %s \"%s\"" (13-18) + {literal: "creating ", exact: false, kind: KindCreating, shape: shapeDescQuoted}, + // "dropping %s %s" (13-18) + {literal: "dropping ", exact: false, kind: KindDropping, shape: shapeDescTag}, +} diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 0ce6652..fab93f6 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -4,6 +4,10 @@ // locking, which doubles, splits, or drops that prefix mid-line. Lines it can't // classify become KindUnknown rather than errors, so wording drift across // PostgreSQL versions never breaks the pipeline. +// +// The wordings it matches on are not hand-written: messages_gen.go is generated +// from pg_dump's own gettext catalogs across the supported releases (see +// tools/pgmsg), and messages.go binds each one to the Event it means. package parser import ( @@ -71,62 +75,58 @@ func (p *Parser) flushErr() []Event { return []Event{ev} } -// classify maps a de-prefixed body to an Event. raw is the original line, kept -// for the KindUnknown fallback. ok is false only for context-only lines that -// produce no event (e.g. "from TOC entry", "while PROCESSING TOC:"). +// classify maps a de-prefixed body to an Event, matching it against the +// generated message table (messages_gen.go). raw is the original line, kept for +// the KindUnknown fallback. ok is false only for context-only lines that produce +// no event of their own (the "from TOC entry" line). func (p *Parser) classify(body, raw string) (Event, bool) { - switch { - case body == "connecting to database for restore", - body == "entering main parallel loop", - body == "finished main parallel loop", - body == "while PROCESSING TOC:": - return Event{Kind: KindInfo, Raw: body}, true - - case strings.HasPrefix(body, "from TOC entry "): - // The remainder is a TOC listing line; reuse the toc parser for its id. - if e, ok := toc.ParseListingLine(strings.TrimPrefix(body, "from TOC entry ")); ok { + // Severity tags are part of the envelope - they come from + // src/common/logging.c, not pg_dump's message catalog - so they're matched + // here rather than in the generated table. + if msg, ok := cut(body, "error: "); ok { + ev := Event{Kind: KindError, Message: msg, DumpID: p.pendingCtxID} + p.pendingCtxID = 0 + return ev, true + } + if msg, ok := cut(body, "warning: "); ok { + return Event{Kind: KindWarning, Message: msg}, true + } + + m, args, ok := matchMessage(body) + if !ok { + return Event{Kind: KindUnknown, Raw: raw}, true + } + + switch m.shape { + case shapeTOCEntry: + // Error context, not an event of its own: the remainder is a TOC + // listing line, so reuse the toc parser for its id. + if e, ok := toc.ParseListingLine(args); ok { p.pendingCtxID = e.DumpID } return Event{}, false - case strings.HasPrefix(body, "dropping "): - desc, tag := splitDescTag(strings.TrimPrefix(body, "dropping ")) - return Event{Kind: KindDropping, Desc: desc, Tag: tag}, true + case shapeDescTag: + desc, tag := splitDescTag(args) + return Event{Kind: m.kind, Desc: desc, Tag: tag}, true - case strings.HasPrefix(body, "creating "): - desc, name := splitDescQuoted(strings.TrimPrefix(body, "creating ")) - return Event{Kind: KindCreating, Desc: desc, Name: name}, true + case shapeDescName: + desc, name := splitDescTag(args) + return Event{Kind: m.kind, Desc: desc, Name: name}, true - case strings.HasPrefix(body, "processing data for table "): - return Event{Kind: KindProcessingData, Name: unquote(strings.TrimPrefix(body, "processing data for table "))}, true + case shapeDescQuoted: + desc, name := splitDescQuoted(args) + return Event{Kind: m.kind, Desc: desc, Name: name}, true - case strings.HasPrefix(body, "processing item "): - id, desc, tag := splitItem(strings.TrimPrefix(body, "processing item ")) - return Event{Kind: KindProcessingItem, DumpID: id, Desc: desc, Tag: tag}, true + case shapeQuotedName: + return Event{Kind: m.kind, Name: unquote(args)}, true - case strings.HasPrefix(body, "launching item "): - id, desc, tag := splitItem(strings.TrimPrefix(body, "launching item ")) - return Event{Kind: KindLaunchItem, DumpID: id, Desc: desc, Tag: tag}, true + case shapeItem: + id, desc, tag := splitItem(args) + return Event{Kind: m.kind, DumpID: id, Desc: desc, Tag: tag}, true - case strings.HasPrefix(body, "finished item "): - id, desc, tag := splitItem(strings.TrimPrefix(body, "finished item ")) - return Event{Kind: KindFinishItem, DumpID: id, Desc: desc, Tag: tag}, true - - case strings.HasPrefix(body, "executing "): - desc, name := splitDescTag(strings.TrimPrefix(body, "executing ")) - return Event{Kind: KindExecuting, Desc: desc, Name: name}, true - - case strings.HasPrefix(body, "error: "): - msg := strings.TrimPrefix(body, "error: ") - ev := Event{Kind: KindError, Message: msg, DumpID: p.pendingCtxID} - p.pendingCtxID = 0 - return ev, true - - case strings.HasPrefix(body, "warning: "): - return Event{Kind: KindWarning, Message: strings.TrimPrefix(body, "warning: ")}, true - - default: - return Event{Kind: KindUnknown, Raw: raw}, true + default: // shapeNone: the message is its own meaning + return Event{Kind: m.kind, Raw: body}, true } } diff --git a/internal/parser/parser_test.go b/internal/parser/parser_test.go index b2780fd..5870cb9 100644 --- a/internal/parser/parser_test.go +++ b/internal/parser/parser_test.go @@ -194,3 +194,42 @@ func TestParallelInterleaving(t *testing.T) { t.Errorf("parsed %d errors, pg_restore reported %d", got, want) } } + +// TestMessageTableOrder guards the invariant matchMessage depends on and the +// generator provides: longest literal first, so a specific message can never be +// shadowed by a shorter one that happens to share its opening words. +func TestMessageTableOrder(t *testing.T) { + for i := 1; i < len(messages); i++ { + if len(messages[i-1].literal) < len(messages[i].literal) { + t.Fatalf("table out of order at %d: %q before %q - regenerate with `just gen-messages`", + i, messages[i-1].literal, messages[i].literal) + } + } + + // Every literal has to be reachable: a literal that another entry already + // matches in full would be dead weight in the scan. + for i, m := range messages { + if got, _, ok := matchMessage(m.literal); ok && got.literal != m.literal { + t.Errorf("entry %d (%q) is shadowed by %q", i, m.literal, got.literal) + } + } +} + +// TestMessageTableCovers pins the kinds the table is expected to carry, so a +// regeneration that silently dropped a binding fails here rather than showing +// up as a stalled progress bar during a restore. +func TestMessageTableCovers(t *testing.T) { + want := []Kind{ + KindInfo, KindDropping, KindCreating, KindProcessingData, + KindProcessingItem, KindLaunchItem, KindFinishItem, KindExecuting, + } + have := map[Kind]bool{} + for _, m := range messages { + have[m.kind] = true + } + for _, k := range want { + if !have[k] { + t.Errorf("no message maps to %s", k) + } + } +} diff --git a/internal/render/frame.go b/internal/render/frame.go index a409f8e..abf4cc8 100644 --- a/internal/render/frame.go +++ b/internal/render/frame.go @@ -94,9 +94,9 @@ func Frame(s aggregator.Snapshot, opt Opts) []string { if cl := cleanupLine(st, s, opt.Spinner); cl != "" { add(" %-10s %s", "cleanup", cl) } - add(" %s", phaseBar(st, "pre-data", fillPre, s.Pre, "")) - add(" %s", phaseBar(st, "data", fillData, s.Data, dataNote(s))) - add(" %s", phaseBar(st, "post-data", fillPost, s.Post, "")) + for _, row := range phaseRows(st, s) { + add(" %s", row) + } // The working line sits below all three bars: under -j, data and post-data // items run concurrently, so it reflects current activity across the restore. // Its spinner and live timer are what tell a long single item apart from a hang. @@ -140,6 +140,46 @@ func groupLimit(maxLines, used int) int { return min(maxGroups, max(maxLines-used-1, 0)) // -1 reserves the "… N more" row } +// phaseRows renders the three phase rows: bars when preflight supplied +// denominators, bare counts when it couldn't (countless mode). Frame and +// Summary share it so the block appears to freeze in place at the end of a run +// rather than change shape. +func phaseRows(st *Styles, s aggregator.Snapshot) []string { + if s.Countless { + return []string{ + phaseCount(st, "pre-data", s.Pre), + phaseCount(st, "data", s.Data), + phaseCount(st, "post-data", s.Post), + } + } + return []string{ + phaseBar(st, "pre-data", fillPre, s.Pre, ""), + phaseBar(st, "data", fillData, s.Data, dataNote(s)), + phaseBar(st, "post-data", fillPost, s.Post, ""), + } +} + +// phaseCount renders a phase with no denominator to draw against: the running +// object count where the bar would be, and nothing that implies a fraction. The +// count sits in the bar's own column so the three rows stay aligned with each +// other and with the cleanup row above them. +func phaseCount(st *Styles, name string, p aggregator.PhaseProgress) string { + count := fmt.Sprintf("%d %s", p.Done, objectWord(p.Done)) + line := fmt.Sprintf("%-10s %s", name, count) + if !p.Complete { + return line + } + pad := max(barWidth-ansi.StringWidth(count), 1) + return line + strings.Repeat(" ", pad) + " " + st.done.Render("done") +} + +func objectWord(n int) string { + if n == 1 { + return "object" + } + return "objects" +} + // phaseBar renders "name ▓▓▓░░░ done/total pct" with an optional trailing // note. fill is the phase's filled-cell glyph; the empty track is uniform. A // complete phase reads 100% and "done" even if pg_restore skipped some entries - diff --git a/internal/render/plain.go b/internal/render/plain.go index f57203a..3191d8f 100644 --- a/internal/render/plain.go +++ b/internal/render/plain.go @@ -3,14 +3,25 @@ package render import ( "fmt" "io" + "strconv" "time" "github.com/amberpixels/ele/internal/aggregator" "github.com/amberpixels/years" ) +// countlessStep and countlessInterval pace the line when there are no +// denominators to hit deciles against: a milestone is every N objects, or every +// N seconds, whichever comes first. Without them a countless restore would +// print one line at the start and then nothing for the rest of the run. +const ( + countlessStep = 50 + countlessInterval = 15 * time.Second +) + // PlainProgress emits a one-line status to w at meaningful milestones - each -// phase completion and every 10% within a phase. It is the degraded-mode +// phase completion and every 10% within a phase, or, with no denominators to +// measure against, every countlessStep objects. It is the degraded-mode // substitute for the live repaint block (non-TTY, CI, NO_COLOR, ELE_PLAIN), // never the raw firehose. Feed it snapshots on a ticker. type PlainProgress struct { @@ -21,6 +32,11 @@ type PlainProgress struct { preDone bool dataDecile int postDecile int + + // countless pacing: the object count and the elapsed reading at the last + // emitted line. + lastCount int + lastEmit time.Duration } // NewPlainProgress returns an emitter writing to w. @@ -34,6 +50,18 @@ func (p *PlainProgress) Update(s aggregator.Snapshot, elapsed time.Duration) { milestone := !p.started p.started = true + if s.Countless { + done := s.Pre.Done + s.Data.Done + s.Post.Done + if done-p.lastCount >= countlessStep || elapsed-p.lastEmit >= countlessInterval { + milestone = true + } + if milestone { + p.lastCount, p.lastEmit = done, elapsed + p.emit(s, elapsed) + } + return + } + if s.Pre.Total > 0 && s.Pre.Done == s.Pre.Total && !p.preDone { p.preDone = true milestone = true @@ -57,9 +85,9 @@ func (p *PlainProgress) emit(s aggregator.Snapshot, elapsed time.Duration) { realStyle = p.st.real } fmt.Fprintf(p.w, "ele · pre %s · data %s · post %s · %d err · %s", - frac(s.Pre.Done, s.Pre.Total), - fracPct(s.Data.Done, s.Data.Total), - fracPct(s.Post.Done, s.Post.Total), + countOr(s.Countless, s.Pre.Done, frac(s.Pre.Done, s.Pre.Total)), + countOr(s.Countless, s.Data.Done, fracPct(s.Data.Done, s.Data.Total)), + countOr(s.Countless, s.Post.Done, fracPct(s.Post.Done, s.Post.Total)), s.ErrTotal, realStyle.Render(fmt.Sprintf("%d real", s.ErrReal)), ) @@ -87,6 +115,15 @@ func decile(done, total int) int { return done * 10 / total } +// countOr is the bare count in countless mode, where "0/0 0%" would be a lie +// dressed as a fraction, and the given fraction otherwise. +func countOr(countless bool, done int, fraction string) string { + if countless { + return strconv.Itoa(done) + } + return fraction +} + func frac(done, total int) string { return fmt.Sprintf("%d/%d", done, total) } func fracPct(done, total int) string { diff --git a/internal/render/render_test.go b/internal/render/render_test.go index 8794128..7bc6fd7 100644 --- a/internal/render/render_test.go +++ b/internal/render/render_test.go @@ -342,3 +342,91 @@ func TestLiveClose(t *testing.T) { t.Error("Close should restore the cursor") } } + +// countlessSample is the stdin restore: counts, no denominators, same errors. +func countlessSample() aggregator.Snapshot { + s := sample() + s.Countless = true + s.Pre = aggregator.PhaseProgress{Done: 1009, Complete: true} + s.Data = aggregator.PhaseProgress{Done: 166} + s.Post = aggregator.PhaseProgress{Done: 4} + return s +} + +// TestFrameCountless: with no plan there is nothing to draw a bar against, so +// the rows carry counts and nothing that implies a fraction. Everything that +// never needed denominators - the working line, the log line, the error panel - +// stays exactly as it was. +func TestFrameCountless(t *testing.T) { + s := countlessSample() + s.Working = []aggregator.WorkItem{{Desc: "TABLE DATA", Name: "activity_logs"}} + out := joined(Frame(s, Opts{Title: "throwaway", LogPath: "run.log", Spinner: '⣾'})) + + for _, want := range []string{ + "pre-data 1009 objects", "data 166 objects", "post-data 4 objects", + "done", // pre-data finished, and says so without a bar + "activity_logs", // working line intact + "run.log", + "1909 total", "0 real", + } { + if !strings.Contains(out, want) { + t.Errorf("countless frame missing %q:\n%s", want, out) + } + } + for _, unwanted := range []string{"░", "█", "▓", "▒", "%", "/1009"} { + if strings.Contains(out, unwanted) { + t.Errorf("countless frame still shows %q (no denominators exist):\n%s", unwanted, out) + } + } +} + +// The summary mirrors the live block, so it drops the bars too. +func TestSummaryCountless(t *testing.T) { + var buf bytes.Buffer + Summary(&buf, countlessSample(), "run.log", time.Minute, 100) + out := buf.String() + + if !strings.Contains(out, "data 166 objects") { + t.Errorf("countless summary missing the data count:\n%s", out) + } + if strings.Contains(out, "░") || strings.Contains(out, "166/") { + t.Errorf("countless summary still shows a bar or a fraction:\n%s", out) + } + if !strings.Contains(out, "success") { + t.Errorf("countless summary missing the verdict:\n%s", out) + } +} + +// TestPlainProgressCountless: deciles can't fire without totals, so the plain +// line paces on the object count instead. The old rule would have emitted once +// and then gone silent for the whole restore. +func TestPlainProgressCountless(t *testing.T) { + var buf bytes.Buffer + pp := NewPlainProgress(&buf) + + snap := func(pre, data int) aggregator.Snapshot { + return aggregator.Snapshot{ + Countless: true, + Pre: aggregator.PhaseProgress{Done: pre}, + Data: aggregator.PhaseProgress{Done: data}, + } + } + + pp.Update(snap(0, 0), 0) // first tick -> emits + pp.Update(snap(20, 0), time.Second) // under the step, under the interval + pp.Update(snap(60, 0), 2*time.Second) // 60 objects on -> emits + pp.Update(snap(70, 0), 3*time.Second) // only 10 since the last line + pp.Update(snap(70, 0), 20*time.Second) // quiet, but the interval elapsed -> emits + pp.Update(snap(70, 5), 21*time.Second) // nothing new to say + + out := buf.String() + if n := strings.Count(out, "\n"); n != 3 { + t.Errorf("emitted %d lines, want 3:\n%s", n, out) + } + if !strings.Contains(out, "pre 70 · data 0") { + t.Errorf("counts not reported bare:\n%s", out) + } + if strings.Contains(out, "0/0") { + t.Errorf("plain line invented a denominator:\n%s", out) + } +} diff --git a/internal/render/summary.go b/internal/render/summary.go index d464e5c..a2a3354 100644 --- a/internal/render/summary.go +++ b/internal/render/summary.go @@ -26,9 +26,9 @@ func Summary(w io.Writer, s aggregator.Snapshot, logPath string, elapsed time.Du if cl := cleanupLine(st, s, 0); cl != "" { fmt.Fprintf(w, " %-10s %s\n", "cleanup", cl) } - fmt.Fprintf(w, " %s\n", phaseBar(st, "pre-data", fillPre, s.Pre, "")) - fmt.Fprintf(w, " %s\n", phaseBar(st, "data", fillData, s.Data, dataNote(s))) - fmt.Fprintf(w, " %s\n", phaseBar(st, "post-data", fillPost, s.Post, "")) + for _, row := range phaseRows(st, s) { + fmt.Fprintf(w, " %s\n", row) + } if logPath != "" { fmt.Fprintf(w, "\n raw log %s\n", st.dim.Render(logPath)) diff --git a/justfile b/justfile index 5053950..9601ccb 100644 --- a/justfile +++ b/justfile @@ -91,6 +91,23 @@ _golangci-install: test *ARGS: go test {{ARGS}} ./... +# --- Codegen --- +# +# The parser's message table comes from PostgreSQL's own pg_dump catalogs, so a +# new major is a data change: run `gen-messages` when one ships, read the drift +# summary it prints, and commit what moved. + +# Regenerate the message table from upstream release tags - fetches over the network +[group('gen')] +gen-messages: + go run ./tools/pgmsg + +# Regenerate from the committed msgid snapshots; fails if anything moved - immutable +[group('gen')] +gen-messages--check: + go run ./tools/pgmsg -offline + git diff --exit-code internal/parser/messages_gen.go tools/pgmsg/testdata + # --- CI & release --- # Everything CI runs, in CI's order (build, vet, test) - immutable diff --git a/tools/pgmsg/bindings.go b/tools/pgmsg/bindings.go new file mode 100644 index 0000000..a3aea04 --- /dev/null +++ b/tools/pgmsg/bindings.go @@ -0,0 +1,41 @@ +package main + +// binding is one pg_dump message the parser acts on: the upstream msgid, the +// event it means, and how its arguments are read back out of the printed line. +// +// This table is hand-maintained on purpose. A gettext catalog carries wording, +// never meaning, so no generator can decide that "launching item %d %s %s" is +// the start of a parallel item. What the generator does instead is prove every +// line below still exists upstream, and emit the literal text to match on. +type binding struct { + msgid string + kind string // parser.Kind constant + shape string // parser shape constant: which fields the arguments fill +} + +// bindings covers exactly what parser.classify matches on a message body. +// The envelope around it - the "pg_restore:" prefix, the error:/warning:/detail: +// severity tags, the "Command was:" continuation - comes from +// src/common/logging.c rather than pg_dump's catalog, and stays hand-written in +// the parser. +var bindings = []binding{ + {"connecting to database for restore", "KindInfo", "shapeNone"}, + {"entering main parallel loop", "KindInfo", "shapeNone"}, + {"finished main parallel loop", "KindInfo", "shapeNone"}, + {"while INITIALIZING:", "KindInfo", "shapeNone"}, + {"while PROCESSING TOC:", "KindInfo", "shapeNone"}, + {"while FINALIZING:", "KindInfo", "shapeNone"}, + + // Context for the error that follows it; sets parser state, emits nothing. + {"from TOC entry %d; %u %u %s %s %s", "KindUnknown", "shapeTOCEntry"}, + + {"dropping %s %s", "KindDropping", "shapeDescTag"}, + {"creating %s \"%s.%s\"", "KindCreating", "shapeDescQuoted"}, + {"creating %s \"%s\"", "KindCreating", "shapeDescQuoted"}, + {"processing data for table \"%s.%s\"", "KindProcessingData", "shapeQuotedName"}, + {"processing item %d %s %s", "KindProcessingItem", "shapeItem"}, + {"launching item %d %s %s", "KindLaunchItem", "shapeItem"}, + {"finished item %d %s %s", "KindFinishItem", "shapeItem"}, + {"executing %s %s", "KindExecuting", "shapeDescName"}, + {"executing %s", "KindExecuting", "shapeDescName"}, +} diff --git a/tools/pgmsg/main.go b/tools/pgmsg/main.go new file mode 100644 index 0000000..0f602e9 --- /dev/null +++ b/tools/pgmsg/main.go @@ -0,0 +1,373 @@ +// Command pgmsg regenerates the parser's message table from PostgreSQL's own +// message catalogs, so a new major release is a data change rather than a +// guessing game about which wording moved. +// +// It pulls the msgid set of src/bin/pg_dump/po/.po at each supported +// release tag from the GitHub mirror, snapshots it under testdata/, checks the +// hand-maintained bindings (bindings.go) still exist upstream, and writes +// internal/parser/messages_gen.go. +// +// go run ./tools/pgmsg # fetch, snapshot, generate +// go run ./tools/pgmsg -offline # generate from the committed snapshots +// +// The .po files are the source rather than pg_dump.pot: the .pot template is a +// build artifact and is not committed upstream (404 at every release tag), +// while the .po translations carry the identical msgid set. Two languages are +// unioned per tag, since one translation can lag upstream but two are unlikely +// to lag the same message. +package main + +import ( + "flag" + "fmt" + "go/format" + "io" + "log" + "net/http" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "time" +) + +const poURL = "https://raw.githubusercontent.com/postgres/postgres/%s/src/bin/pg_dump/po/%s.po" + +func main() { + log.SetFlags(0) + log.SetPrefix("pgmsg: ") + + tags := flag.String("tags", "REL_13_STABLE,REL_14_STABLE,REL_15_STABLE,REL_16_STABLE,REL_17_STABLE,REL_18_STABLE", + "release tags to read, oldest first") + langs := flag.String("langs", "de,fr", "translations to union per tag") + snapshots := flag.String("snapshots", filepath.Join("tools", "pgmsg", "testdata"), "where msgid snapshots live") + out := flag.String("out", filepath.Join("internal", "parser", "messages_gen.go"), "generated file") + offline := flag.Bool("offline", false, "read the committed snapshots instead of fetching") + flag.Parse() + + tagList := split(*tags) + langList := split(*langs) + if len(tagList) == 0 || len(langList) == 0 { + log.Fatal("need at least one tag and one language") + } + + catalogs, err := load(tagList, langList, *snapshots, *offline) + if err != nil { + log.Fatal(err) + } + reportDrift(tagList, catalogs) + + entries, err := resolve(tagList, catalogs) + if err != nil { + log.Fatal(err) + } + if err := write(*out, entries, tagList, langList); err != nil { + log.Fatal(err) + } + log.Printf("wrote %s: %d message(s) from %d binding(s)", *out, len(entries), len(bindings)) +} + +// --- catalogs ------------------------------------------------------------- + +// load returns the msgid set per tag, fetching and snapshotting it unless the +// committed snapshots were asked for. +func load(tags, langs []string, dir string, offline bool) (map[string]map[string]bool, error) { + catalogs := map[string]map[string]bool{} + for _, tag := range tags { + if offline { + set, err := readSnapshot(filepath.Join(dir, tag+".txt")) + if err != nil { + return nil, err + } + catalogs[tag] = set + continue + } + + set := map[string]bool{} + for _, lang := range langs { + body, err := fetch(fmt.Sprintf(poURL, tag, lang)) + if err != nil { + return nil, fmt.Errorf("%s/%s.po: %w", tag, lang, err) + } + for _, id := range msgids(body) { + set[id] = true + } + } + if len(set) == 0 { + return nil, fmt.Errorf("%s: no msgids found", tag) + } + if err := writeSnapshot(filepath.Join(dir, tag+".txt"), tag, langs, set); err != nil { + return nil, err + } + catalogs[tag] = set + log.Printf("%s: %d msgids", tag, len(set)) + } + return catalogs, nil +} + +func fetch(url string) (string, error) { + client := &http.Client{Timeout: 60 * time.Second} + resp, err := client.Get(url) + if err != nil { + return "", err + } + defer func() { _ = resp.Body.Close() }() + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("GET %s: %s", url, resp.Status) + } + b, err := io.ReadAll(resp.Body) + return string(b), err +} + +// msgids extracts every msgid from a .po file. gettext wraps long strings over +// several lines (`msgid ""` followed by quoted fragments), so a msgid is read +// until the first line that isn't another fragment. +func msgids(po string) []string { + var out []string + lines := strings.Split(po, "\n") + for i := 0; i < len(lines); i++ { + line := strings.TrimSpace(lines[i]) + if !strings.HasPrefix(line, "msgid ") { + continue + } + var b strings.Builder + b.WriteString(unquotePO(strings.TrimPrefix(line, "msgid "))) + for i+1 < len(lines) { + next := strings.TrimSpace(lines[i+1]) + if !strings.HasPrefix(next, `"`) { + break + } + b.WriteString(unquotePO(next)) + i++ + } + if s := b.String(); s != "" { + out = append(out, s) + } + } + return out +} + +// unquotePO resolves one quoted .po fragment, including the C escapes gettext +// uses. Anything that isn't a quoted fragment yields nothing. +func unquotePO(s string) string { + s = strings.TrimSpace(s) + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return "" + } + return strings.NewReplacer(`\"`, `"`, `\\`, `\`, `\n`, "\n", `\t`, "\t").Replace(s[1 : len(s)-1]) +} + +// --- snapshots ------------------------------------------------------------ + +// writeSnapshot records a tag's msgid set, one strconv-quoted msgid per line so +// multi-line messages stay on one line and the file diffs cleanly. Sorted, with +// no timestamp, so regenerating an unchanged tag is a no-op. +func writeSnapshot(path, tag string, langs []string, set map[string]bool) error { + var b strings.Builder + fmt.Fprintf(&b, "# msgid set of src/bin/pg_dump/po/{%s}.po at %s\n", strings.Join(langs, ","), tag) + fmt.Fprintf(&b, "# generated by tools/pgmsg; one Go-quoted msgid per line\n") + for _, id := range sorted(set) { + b.WriteString(strconv.Quote(id) + "\n") + } + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + return err + } + return os.WriteFile(path, []byte(b.String()), 0o644) +} + +func readSnapshot(path string) (map[string]bool, error) { + b, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("reading snapshot (run without -offline to create it): %w", err) + } + set := map[string]bool{} + for _, line := range strings.Split(string(b), "\n") { + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + id, err := strconv.Unquote(line) + if err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + set[id] = true + } + return set, nil +} + +// reportDrift prints how the catalog moved between adjacent releases - the +// cheap early warning that a new major reworded something. +func reportDrift(tags []string, catalogs map[string]map[string]bool) { + for i := 1; i < len(tags); i++ { + prev, cur := catalogs[tags[i-1]], catalogs[tags[i]] + added, removed := 0, 0 + for id := range cur { + if !prev[id] { + added++ + } + } + for id := range prev { + if !cur[id] { + removed++ + } + } + log.Printf("%s -> %s: +%d -%d msgids", tags[i-1], tags[i], added, removed) + } +} + +// --- resolution ----------------------------------------------------------- + +// entry is one row of the generated table: the literal text to match, what it +// means, and the msgids (with their release ranges) that produced it. +type entry struct { + literal string + exact bool + kind string + shape string + sources []string // "msgid" (range), for the row's comment +} + +// resolve checks every binding against the catalogs and folds the bindings that +// share a literal into one row. A binding no release carries is an error: it +// means the parser is matching on wording that no longer exists. +func resolve(tags []string, catalogs map[string]map[string]bool) ([]entry, error) { + byLiteral := map[string]*entry{} + var order []string + var missing []string + + for _, b := range bindings { + var found []string + for _, tag := range tags { + if catalogs[tag][b.msgid] { + found = append(found, tag) + } + } + if len(found) == 0 { + missing = append(missing, b.msgid) + continue + } + + lit, exact := literal(b.msgid) + e := byLiteral[lit] + if e == nil { + e = &entry{literal: lit, exact: exact, kind: b.kind, shape: b.shape} + byLiteral[lit] = e + order = append(order, lit) + } + if e.kind != b.kind || e.shape != b.shape { + return nil, fmt.Errorf("%q: two bindings share a literal but disagree (%s/%s vs %s/%s)", + lit, e.kind, e.shape, b.kind, b.shape) + } + e.sources = append(e.sources, fmt.Sprintf("%s (%s)", strconv.Quote(b.msgid), versions(found))) + } + + if len(missing) > 0 { + return nil, fmt.Errorf("binding(s) absent from every release - upstream reworded them:\n %s", + strings.Join(missing, "\n ")) + } + + // Longest literal first: the most specific match wins, whatever order the + // bindings happen to be written in. + sort.SliceStable(order, func(i, j int) bool { + if len(order[i]) != len(order[j]) { + return len(order[i]) > len(order[j]) + } + return order[i] < order[j] + }) + out := make([]entry, 0, len(order)) + for _, lit := range order { + out = append(out, *byLiteral[lit]) + } + return out, nil +} + +// literal is the text pg_restore prints verbatim: everything before the first +// format verb. A msgid with no verb is matched exactly rather than by prefix. +// +// A quote right before the verb belongs to the argument, not to the literal: +// postgres quotes every identifier, and the parser's unquote is what reads that +// back. Leaving it in the literal would also make the match intolerant of a +// release that stopped quoting there. +func literal(msgid string) (lit string, exact bool) { + if i := strings.IndexByte(msgid, '%'); i >= 0 { + return strings.TrimSuffix(msgid[:i], `"`), false + } + return msgid, true +} + +// versions renders the majors a msgid was found in, compressing runs: "13-18", +// "17-18", "13, 16-18". +func versions(tags []string) string { + var majors []string + for _, t := range tags { + majors = append(majors, strings.TrimSuffix(strings.TrimPrefix(t, "REL_"), "_STABLE")) + } + var parts []string + for i := 0; i < len(majors); { + j := i + for j+1 < len(majors) && consecutive(majors[j], majors[j+1]) { + j++ + } + if i == j { + parts = append(parts, majors[i]) + } else { + parts = append(parts, majors[i]+"-"+majors[j]) + } + i = j + 1 + } + return strings.Join(parts, ", ") +} + +func consecutive(a, b string) bool { + x, err1 := strconv.Atoi(a) + y, err2 := strconv.Atoi(b) + return err1 == nil && err2 == nil && y == x+1 +} + +// --- output --------------------------------------------------------------- + +func write(path string, entries []entry, tags, langs []string) error { + var b strings.Builder + b.WriteString("// Code generated by tools/pgmsg. DO NOT EDIT.\n//\n") + fmt.Fprintf(&b, "// Source: src/bin/pg_dump/po/{%s}.po at %s .. %s\n", + strings.Join(langs, ","), tags[0], tags[len(tags)-1]) + b.WriteString("// (github.com/postgres/postgres). Regenerate with `just gen-messages`.\n\n") + b.WriteString("package parser\n\n") + b.WriteString("// messages is what pg_restore prints, mapped to what it means. Ordered\n") + b.WriteString("// longest-literal-first, so the first match is the most specific one.\n") + b.WriteString("var messages = []message{\n") + for _, e := range entries { + fmt.Fprintf(&b, "\t// %s\n", strings.Join(e.sources, ", ")) + fmt.Fprintf(&b, "\t{literal: %s, exact: %t, kind: %s, shape: %s},\n", + strconv.Quote(e.literal), e.exact, e.kind, e.shape) + } + b.WriteString("}\n") + + src, err := format.Source([]byte(b.String())) + if err != nil { + return fmt.Errorf("formatting generated source: %w", err) + } + return os.WriteFile(path, src, 0o644) +} + +// --- helpers -------------------------------------------------------------- + +func split(s string) []string { + var out []string + for _, p := range strings.Split(s, ",") { + if p = strings.TrimSpace(p); p != "" { + out = append(out, p) + } + } + return out +} + +func sorted(set map[string]bool) []string { + out := make([]string, 0, len(set)) + for k := range set { + out = append(out, k) + } + sort.Strings(out) + return out +} diff --git a/tools/pgmsg/testdata/REL_13_STABLE.txt b/tools/pgmsg/testdata/REL_13_STABLE.txt new file mode 100644 index 0000000..6f389b0 --- /dev/null +++ b/tools/pgmsg/testdata/REL_13_STABLE.txt @@ -0,0 +1,510 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_13_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-comments do not dump comments\n" +" --no-comments do not restore comments\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-blobs exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=0-9 compression level for compressed formats\n" +" -a, --data-only dump only the data, not the schema\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --blobs include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump the specified table(s) only\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s dumps a database as a text file or to other formats.\n\n" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +"%s home page: <%s>\n" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s: %sCommand was: %s" +"(The system catalogs might be corrupted.)" +"COPY failed for table \"%s\": %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Exported snapshots are not supported by this server version." +"Password: " +"Report bugs to <%s>.\n" +"Synchronized snapshots are not supported by this server version.\nRun with --no-synchronized-snapshots instead if you do not need\nsynchronized snapshots." +"Synchronized snapshots on standby servers are not supported by this server version.\nRun with --no-synchronized-snapshots instead if you do not need\nsynchronized snapshots." +"The command was: %s" +"The program \"%s\" is needed by %s but was not found in the\nsame directory as \"%s\".\nCheck your installation." +"The program \"%s\" was found by \"%s\"\nbut was not the same version as %s.\nCheck your installation." +"Try \"%s --help\" for more information.\n" +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"WSAStartup failed: %d" +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%s) does not match expected (%s)" +"aggregate function %s could not be dumped correctly for this database version; ignored" +"already connected to a database" +"archive is compressed, but this installation does not support compression -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"bogus value in proargmodes array" +"can only reopen input archives" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (compression not supported in this installation)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression is not supported by tar archive format" +"compression level must be in range 0..9" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"connection to database \"%s\" failed: %s" +"corrupt tar header found in %s (expected %d, computed %d) file position %s" +"could not change directory to \"%s\": %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close blob data file: %m" +"could not close blobs TOC file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close directory \"%s\": %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close tar member: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database" +"could not connect to database \"%s\"" +"could not connect to database \"%s\": %s" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not determine seek position in archive file: %m" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get server version" +"could not get server_version from libpq" +"could not identify current directory: %m" +"could not identify dependency loop" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not open temporary file" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse proallargtypes array" +"could not parse proargmodes array" +"could not parse proargnames array" +"could not parse proconfig array" +"could not parse reloptions array" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not parse subpublications array" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\"" +"could not read directory \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not read symbolic link \"%s\": %m" +"could not resolve dependency loop among these items:" +"could not set default_table_access_method: %s" +"could not set default_tablespace to %s: %s" +"could not set search_path to \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not uncompress data: %s" +"could not write to blobs TOC file" +"could not write to large object (result: %lu, expected: %lu)" +"could not write to output file: %s" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"data block %d has wrong seek position" +"definition of view \"%s\" appears to be empty (length zero)" +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"extra_float_digits must be in range -15..3" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"fatal: " +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding check constraints for table \"%s.%s\"" +"finding default expressions of table \"%s.%s\"" +"finding extension tables" +"finding inheritance relationships" +"finding the columns and types of table \"%s.%s\"" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found orphaned pg_auth_members entry for role %s" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"identifying extension members" +"implied data-only restore" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive" +"input file does not appear to be a valid archive (too short?)" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +"invalid binary \"%s\"" +"invalid client encoding \"%s\" specified" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression code: %d" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid message received from worker: \"%s\"" +"invalid number of parallel jobs" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"maximum number of parallel jobs is %d" +"missing index for constraint \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"not built with zlib support" +"one of -d/--dbname and -f/--file must be specified" +"option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +"option --if-exists requires option -c/--clean" +"option --include-foreign-data is not supported with parallel backup" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +"option --restrict-key can only be used with --format=plain" +"options -C/--create and -1/--single-transaction cannot be used together" +"options -c/--clean and -a/--data-only cannot be used together" +"options -d/--dbname and --restrict-key cannot be used together" +"options -d/--dbname and -f/--file cannot be used together" +"options -g/--globals-only and -r/--roles-only cannot be used together" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +"options -s/--schema-only and --include-foreign-data cannot be used together" +"options -s/--schema-only and -a/--data-only cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"owner of aggregate function \"%s\" appears to be invalid" +"owner of data type \"%s\" appears to be invalid" +"owner of function \"%s\" appears to be invalid" +"owner of operator \"%s\" appears to be invalid" +"owner of operator class \"%s\" appears to be invalid" +"owner of operator family \"%s\" appears to be invalid" +"owner of publication \"%s\" appears to be invalid" +"owner of schema \"%s\" appears to be invalid" +"owner of subscription \"%s\" appears to be invalid" +"owner of table \"%s\" appears to be invalid" +"parallel backup only supported by the directory format" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pclose failed: %m" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"pgpipe: getsockname() failed: error code %d" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"query failed: %s" +"query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"query was: %s" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading foreign key constraints for table \"%s.%s\"" +"reading indexes" +"reading indexes for table \"%s.%s\"" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading triggers for table \"%s.%s\"" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"reconnection to database \"%s\" failed: %s" +"requested compression not available in this installation -- archive will be uncompressed" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"rows-per-insert must be in range %d..%d" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving database definition" +"saving encoding = %s" +"saving large objects" +"saving search_path = %s" +"saving standard_conforming_strings = %s" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"select() failed: %m" +"server version: %s; %s version: %s" +"skipping item %d %s %s" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unexpected COPY statement syntax: \"%s\"" +"unexpected data offset flag %d" +"unexpected extra results during COPY of table \"%s\"" +"unexpected policy command type: %c" +"unexpected section code %d" +"unexpected tgtype value: %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from master: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %s" +"unsupported version (%d.%d) in file header" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %lu byte of large object data (result = %lu)" diff --git a/tools/pgmsg/testdata/REL_14_STABLE.txt b/tools/pgmsg/testdata/REL_14_STABLE.txt new file mode 100644 index 0000000..2cc301c --- /dev/null +++ b/tools/pgmsg/testdata/REL_14_STABLE.txt @@ -0,0 +1,524 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_14_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-comments do not dump comments\n" +" --no-comments do not restore comments\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-toast-compression do not dump TOAST compression methods\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-blobs exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=0-9 compression level for compressed formats\n" +" -a, --data-only dump only the data, not the schema\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --blobs include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -e, --extension=PATTERN dump the specified extension(s) only\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump the specified table(s) only\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s dumps a database as a text file or to other formats.\n\n" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +"%s home page: <%s>\n" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s() failed: %m" +"%s() failed: error code %d" +"%s: %sCommand was: %s" +"(The system catalogs might be corrupted.)" +"COPY failed for table \"%s\": %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Exported snapshots are not supported by this server version." +"Password: " +"Report bugs to <%s>.\n" +"Synchronized snapshots are not supported by this server version.\nRun with --no-synchronized-snapshots instead if you do not need\nsynchronized snapshots." +"Synchronized snapshots on standby servers are not supported by this server version.\nRun with --no-synchronized-snapshots instead if you do not need\nsynchronized snapshots." +"The command was: %s" +"The program \"%s\" is needed by %s but was not found in the\nsame directory as \"%s\".\nCheck your installation." +"The program \"%s\" was found by \"%s\"\nbut was not the same version as %s.\nCheck your installation." +"Try \"%s --help\" for more information.\n" +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"You are currently not connected to a database." +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%s) does not match expected (%s)" +"already connected to a database" +"archive is compressed, but this installation does not support compression -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"bogus value in proargmodes array" +"can only reopen input archives" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (compression not supported in this installation)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression is not supported by tar archive format" +"compression level must be in range 0..9" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"corrupt tar header found in %s (expected %d, computed %d) file position %s" +"could not change directory to \"%s\": %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close blob data file: %m" +"could not close blobs TOC file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close directory \"%s\": %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close tar member: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database" +"could not connect to database \"%s\"" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not create worker thread: %m" +"could not determine seek position in archive file: %m" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get server version" +"could not get server_version from libpq" +"could not identify current directory: %m" +"could not identify dependency loop" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not open temporary file" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse extension condition array" +"could not parse extension configuration array" +"could not parse index statistic columns" +"could not parse index statistic values" +"could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse proallargtypes array" +"could not parse proargmodes array" +"could not parse proargnames array" +"could not parse proconfig array" +"could not parse reloptions array" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not parse subpublications array" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\"" +"could not read directory \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not read symbolic link \"%s\": %m" +"could not resolve dependency loop among these items:" +"could not set default_table_access_method: %s" +"could not set default_tablespace to %s: %s" +"could not set search_path to \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not uncompress data: %s" +"could not write to blobs TOC file" +"could not write to large object: %s" +"could not write to output file: %s" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"cross-database references are not implemented: %s" +"data block %d has wrong seek position" +"definition of view \"%s\" appears to be empty (length zero)" +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"extra_float_digits must be in range -15..3" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"fatal: " +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding check constraints for table \"%s.%s\"" +"finding default expressions of table \"%s.%s\"" +"finding extension tables" +"finding inheritance relationships" +"finding the columns and types of table \"%s.%s\"" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found orphaned pg_auth_members entry for role %s" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"identifying extension members" +"implied data-only restore" +"improper qualified name (too many dotted names): %s" +"improper relation name (too many dotted names): %s" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive" +"input file does not appear to be a valid archive (too short?)" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +"invalid binary \"%s\"" +"invalid client encoding \"%s\" specified" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression code: %d" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid memory allocation request size %zu * %zu\n" +"invalid memory allocation request size %zu + %zu\n" +"invalid message received from worker: \"%s\"" +"invalid number of parallel jobs" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"maximum number of parallel jobs is %d" +"mismatched number of columns and values for index statistics" +"mismatched number of configurations and conditions for extension" +"missing index for constraint \"%s\"" +"no matching extensions were found" +"no matching extensions were found for pattern \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"not built with zlib support" +"one of -d/--dbname and -f/--file must be specified" +"option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +"option --if-exists requires option -c/--clean" +"option --include-foreign-data is not supported with parallel backup" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +"option --restrict-key can only be used with --format=plain" +"options -C/--create and -1/--single-transaction cannot be used together" +"options -c/--clean and -a/--data-only cannot be used together" +"options -d/--dbname and --restrict-key cannot be used together" +"options -d/--dbname and -f/--file cannot be used together" +"options -g/--globals-only and -r/--roles-only cannot be used together" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +"options -s/--schema-only and --include-foreign-data cannot be used together" +"options -s/--schema-only and -a/--data-only cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"owner of aggregate function \"%s\" appears to be invalid" +"owner of data type \"%s\" appears to be invalid" +"owner of function \"%s\" appears to be invalid" +"owner of operator \"%s\" appears to be invalid" +"owner of operator class \"%s\" appears to be invalid" +"owner of operator family \"%s\" appears to be invalid" +"owner of publication \"%s\" appears to be invalid" +"owner of schema \"%s\" appears to be invalid" +"owner of subscription \"%s\" appears to be invalid" +"owner of table \"%s\" appears to be invalid" +"parallel backup only supported by the directory format" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: %s() failed: error code %d" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"postfix operators are not supported anymore (operator \"%s\")" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"query failed: %s" +"query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"query was: %s" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading foreign key constraints for table \"%s.%s\"" +"reading indexes" +"reading indexes for table \"%s.%s\"" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading triggers for table \"%s.%s\"" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"reconnection failed: %s" +"requested compression not available in this installation -- archive will be uncompressed" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"rows-per-insert must be in range %d..%d" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving database definition" +"saving encoding = %s" +"saving large objects" +"saving search_path = %s" +"saving standard_conforming_strings = %s" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"server version: %s; %s version: %s" +"skipping item %d %s %s" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unexpected COPY statement syntax: \"%s\"" +"unexpected data offset flag %d" +"unexpected extra results during COPY of table \"%s\"" +"unexpected policy command type: %c" +"unexpected section code %d" +"unexpected tgtype value: %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from leader: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %s" +"unsupported version (%d.%d) in file header" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %zu byte of large object data (result = %d)" diff --git a/tools/pgmsg/testdata/REL_15_STABLE.txt b/tools/pgmsg/testdata/REL_15_STABLE.txt new file mode 100644 index 0000000..20bd19e --- /dev/null +++ b/tools/pgmsg/testdata/REL_15_STABLE.txt @@ -0,0 +1,505 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_15_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-comments do not dump comments\n" +" --no-comments do not restore comments\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-table-access-method do not dump table access methods\n" +" --no-table-access-method do not restore table access methods\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-toast-compression do not dump TOAST compression methods\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-blobs exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=0-9 compression level for compressed formats\n" +" -a, --data-only dump only the data, not the schema\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --blobs include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -e, --extension=PATTERN dump the specified extension(s) only\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump the specified table(s) only\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s dumps a database as a text file or to other formats.\n\n" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +"%s home page: <%s>\n" +"%s must be in range %d..%d" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s() failed: %m" +"%s() failed: error code %d" +"%s: %sCommand was: %s" +"COPY failed for table \"%s\": %s" +"Command was: %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Password: " +"Query was: %s" +"Report bugs to <%s>.\n" +"The system catalogs might be corrupted." +"Try \"%s --help\" for more information." +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"You are currently not connected to a database." +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%lld) does not match expected (%lld)" +"already connected to a database" +"archive is compressed, but this installation does not support compression -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"can only reopen input archives" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (compression not supported in this installation)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression is not supported by tar archive format" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"corrupt tar header found in %s (expected %d, computed %d) file position %llu" +"could not change directory to \"%s\": %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close blob data file: %m" +"could not close blobs TOC file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close directory \"%s\": %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database" +"could not connect to database \"%s\"" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not create worker thread: %m" +"could not determine seek position in archive file: %m" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get server version" +"could not get server_version from libpq" +"could not identify current directory: %m" +"could not identify dependency loop" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not parse %s array" +"could not parse ACL list (%s) for parameter \"%s\"" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse index statistic columns" +"could not parse index statistic values" +"could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\"" +"could not read directory \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not read symbolic link \"%s\": %m" +"could not resolve dependency loop among these items:" +"could not set default_table_access_method: %s" +"could not set default_tablespace to %s: %s" +"could not set search_path to \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not uncompress data: %s" +"could not write to blobs TOC file" +"could not write to large object: %s" +"could not write to output file: %s" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"cross-database references are not implemented: %s" +"data block %d has wrong seek position" +"definition of view \"%s\" appears to be empty (length zero)" +"detail: " +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding extension tables" +"finding inheritance relationships" +"finding table check constraints" +"finding table default expressions" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found orphaned pg_auth_members entry for role %s" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"hint: " +"identifying extension members" +"implied data-only restore" +"improper qualified name (too many dotted names): %s" +"improper relation name (too many dotted names): %s" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive" +"input file does not appear to be a valid archive (too short?)" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +"invalid binary \"%s\"" +"invalid client encoding \"%s\" specified" +"invalid collation \"%s\"" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression code: %d" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid memory allocation request size %zu * %zu\n" +"invalid memory allocation request size %zu + %zu\n" +"invalid message received from worker: \"%s\"" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"invalid value \"%s\" for option %s" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"mismatched number of columns and values for index statistics" +"mismatched number of configurations and conditions for extension" +"missing index for constraint \"%s\"" +"no matching extensions were found" +"no matching extensions were found for pattern \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"not built with zlib support" +"one of -d/--dbname and -f/--file must be specified" +"option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +"option --if-exists requires option -c/--clean" +"option --include-foreign-data is not supported with parallel backup" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +"option --restrict-key can only be used with --format=plain" +"options -C/--create and -1/--single-transaction cannot be used together" +"options -c/--clean and -a/--data-only cannot be used together" +"options -d/--dbname and --restrict-key cannot be used together" +"options -d/--dbname and -f/--file cannot be used together" +"options -g/--globals-only and -r/--roles-only cannot be used together" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +"options -s/--schema-only and --include-foreign-data cannot be used together" +"options -s/--schema-only and -a/--data-only cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"parallel backup only supported by the directory format" +"parallel dumps from standby servers are not supported by this server version" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: %s() failed: error code %d" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"postfix operators are not supported anymore (operator \"%s\")" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +"program \"%s\" was found by \"%s\" but was not the same version as %s" +"query failed: %s" +"query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading indexes" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership of schemas" +"reading publication membership of tables" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"reconnection failed: %s" +"requested compression not available in this installation -- archive will be uncompressed" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"role with OID %u does not exist" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving database definition" +"saving encoding = %s" +"saving large objects" +"saving search_path = %s" +"saving standard_conforming_strings = %s" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"server version: %s; %s version: %s" +"skipping item %d %s %s" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unexpected COPY statement syntax: \"%s\"" +"unexpected column data for table \"%s\"" +"unexpected data offset flag %d" +"unexpected extra results during COPY of table \"%s\"" +"unexpected index data for table \"%s\"" +"unexpected policy command type: %c" +"unexpected section code %d" +"unexpected tgtype value: %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from leader: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized locale provider: %s" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %s" +"unrecognized table OID %u" +"unsupported pg_init_privs entry: %u %u %d" +"unsupported version (%d.%d) in file header" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %zu byte of large object data (result = %d)" diff --git a/tools/pgmsg/testdata/REL_16_STABLE.txt b/tools/pgmsg/testdata/REL_16_STABLE.txt new file mode 100644 index 0000000..773b6b3 --- /dev/null +++ b/tools/pgmsg/testdata/REL_16_STABLE.txt @@ -0,0 +1,537 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_16_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --blobs (same as --large-objects, deprecated)\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-table-and-children=PATTERN\n do NOT dump the specified table(s), including\n child and partition tables\n" +" --exclude-table-data-and-children=PATTERN\n do NOT dump data for the specified table(s),\n including child and partition tables\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-blobs (same as --no-large-objects, deprecated)\n" +" --no-comments do not dump comments\n" +" --no-comments do not restore comments\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-table-access-method do not dump table access methods\n" +" --no-table-access-method do not restore table access methods\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-toast-compression do not dump TOAST compression methods\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --table-and-children=PATTERN dump only the specified table(s), including\n child and partition tables\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-large-objects exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=METHOD[:DETAIL]\n compress as specified\n" +" -a, --data-only dump only the data, not the schema\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --large-objects include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -e, --extension=PATTERN dump the specified extension(s) only\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump only the specified table(s)\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s dumps a database as a text file or to other formats.\n\n" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +"%s home page: <%s>\n" +"%s must be in range %d..%d" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s() failed: %m" +"%s() failed: error code %d" +"%s: %sCommand was: %s" +"COPY failed for table \"%s\": %s" +"Command was: %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Password: " +"Query was: %s" +"Report bugs to <%s>.\n" +"The system catalogs might be corrupted." +"This grant will be dumped without GRANTED BY." +"Try \"%s --help\" for more information." +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"You are currently not connected to a database." +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%lld) does not match expected (%lld)" +"already connected to a database" +"archive is compressed, but this installation does not support compression (%s) -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"can only reopen input archives" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (%s)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression algorithm \"%s\" does not accept a compression level" +"compression algorithm \"%s\" does not accept a worker count" +"compression algorithm \"%s\" does not support long-distance mode" +"compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)" +"compression is not supported by tar archive format" +"compression option \"%s\" is not currently supported by pg_dump" +"compression option \"%s\" requires a value" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"corrupt tar header found in %s (expected %d, computed %d) file position %llu" +"could not close LO data file: %m" +"could not close LOs TOC file: %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close directory \"%s\": %m" +"could not close file: %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database" +"could not connect to database \"%s\"" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create LZ4 decompression context: %s" +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not create worker thread: %m" +"could not decompress data: %s" +"could not decompress: %s" +"could not determine seek position in archive file: %m" +"could not end compression: %s" +"could not end decompression: %s" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find a legal dump ordering for memberships in role \"%s\"" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not free LZ4 decompression context: %s" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get server version" +"could not get server_version from libpq" +"could not identify dependency loop" +"could not initialize LZ4 compression: %s" +"could not initialize compression library" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not open stdout for appending: %m" +"could not parse %s array" +"could not parse ACL list (%s) for parameter \"%s\"" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse index statistic columns" +"could not parse index statistic values" +"could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\": %m" +"could not read directory \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not resolve dependency loop among these items:" +"could not resolve path \"%s\" to absolute form: %m" +"could not set compression parameter \"%s\": %s" +"could not set default_table_access_method: %s" +"could not set default_tablespace to %s: %s" +"could not set search_path to \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not uncompress data: %s" +"could not write to file: %m" +"could not write to file: %s" +"could not write to large object: %s" +"could not write to output file: %m" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"cross-database references are not implemented: %s" +"data block %d has wrong seek position" +"definition of view \"%s\" appears to be empty (length zero)" +"detail: " +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error during writing: %m" +"error during writing: %s" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding extension tables" +"finding inheritance relationships" +"finding table check constraints" +"finding table default expressions" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found empty string where a compression option was expected" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"grant of role \"%s\" to \"%s\" has invalid grantor OID %s" +"hint: " +"identifying extension members" +"ignoring role grant for missing role with OID %s" +"ignoring role grant to missing role with OID %s" +"implied data-only restore" +"improper qualified name (too many dotted names): %s" +"improper relation name (too many dotted names): %s" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive" +"input file does not appear to be a valid archive (too short?)" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +"invalid binary \"%s\": %m" +"invalid client encoding \"%s\" specified" +"invalid collation \"%s\"" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression specification: %s" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid memory allocation request size %zu * %zu\n" +"invalid memory allocation request size %zu + %zu\n" +"invalid message received from worker: \"%s\"" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"invalid value \"%s\" for option %s" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"mismatched number of columns and values for index statistics" +"mismatched number of configurations and conditions for extension" +"missing index for constraint \"%s\"" +"no matching extensions were found" +"no matching extensions were found for pattern \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"one of -d/--dbname and -f/--file must be specified" +"option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +"option --if-exists requires option -c/--clean" +"option --include-foreign-data is not supported with parallel backup" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +"option --restrict-key can only be used with --format=plain" +"options -C/--create and -1/--single-transaction cannot be used together" +"options -c/--clean and -a/--data-only cannot be used together" +"options -d/--dbname and --restrict-key cannot be used together" +"options -d/--dbname and -f/--file cannot be used together" +"options -g/--globals-only and -r/--roles-only cannot be used together" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +"options -s/--schema-only and --include-foreign-data cannot be used together" +"options -s/--schema-only and -a/--data-only cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"parallel backup only supported by the directory format" +"parallel dumps from standby servers are not supported by this server version" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: %s() failed: error code %d" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"postfix operators are not supported anymore (operator \"%s\")" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +"program \"%s\" was found by \"%s\" but was not the same version as %s" +"query failed: %s" +"query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading indexes" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership of schemas" +"reading publication membership of tables" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"reconnection failed: %s" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"role with OID %u does not exist" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving database definition" +"saving encoding = %s" +"saving large objects" +"saving search_path = %s" +"saving standard_conforming_strings = %s" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"server version: %s; %s version: %s" +"skipping item %d %s %s" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this build does not support compression with %s" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unable to initialize LZ4 library: %s" +"unexpected COPY statement syntax: \"%s\"" +"unexpected column data for table \"%s\"" +"unexpected data offset flag %d" +"unexpected extra results during COPY of table \"%s\"" +"unexpected index data for table \"%s\"" +"unexpected policy command type: %c" +"unexpected section code %d" +"unexpected tgtype value: %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from leader: \"%s\"" +"unrecognized compression algorithm: \"%s\"" +"unrecognized compression option: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized locale provider: %s" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %s" +"unrecognized table OID %u" +"unsupported pg_init_privs entry: %u %u %d" +"unsupported version (%d.%d) in file header" +"value for compression option \"%s\" must be a Boolean value" +"value for compression option \"%s\" must be an integer" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %zu byte of large object data (result = %d)" diff --git a/tools/pgmsg/testdata/REL_17_STABLE.txt b/tools/pgmsg/testdata/REL_17_STABLE.txt new file mode 100644 index 0000000..2880f0d --- /dev/null +++ b/tools/pgmsg/testdata/REL_17_STABLE.txt @@ -0,0 +1,572 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_17_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --blobs (same as --large-objects, deprecated)\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +" --exclude-table-and-children=PATTERN\n do NOT dump the specified table(s), including\n child and partition tables\n" +" --exclude-table-data-and-children=PATTERN\n do NOT dump data for the specified table(s),\n including child and partition tables\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --filter=FILENAME exclude databases based on expressions in FILENAME\n" +" --filter=FILENAME include or exclude objects and data from dump\n based on expressions in FILENAME\n" +" --filter=FILENAME restore or skip objects based on expressions\n in FILENAME\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-blobs (same as --no-large-objects, deprecated)\n" +" --no-comments do not dump comments\n" +" --no-comments do not restore comments\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-table-access-method do not dump table access methods\n" +" --no-table-access-method do not restore table access methods\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-toast-compression do not dump TOAST compression methods\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --sync-method=METHOD set method for syncing files to disk\n" +" --table-and-children=PATTERN dump only the specified table(s), including\n child and partition tables\n" +" --transaction-size=N commit after every N objects\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-large-objects exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=METHOD[:DETAIL]\n compress as specified\n" +" -a, --data-only dump only the data, not the schema\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --large-objects include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -e, --extension=PATTERN dump the specified extension(s) only\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump only the specified table(s)\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s dumps a database as a text file or to other formats.\n\n" +"%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" +"%s filter for \"%s\" is not allowed" +"%s home page: <%s>\n" +"%s must be in range %d..%d" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s() failed: %m" +"%s() failed: error code %d" +"%s: %sCommand was: %s" +"COPY failed for table \"%s\": %s" +"Command was: %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Password: " +"Query was: %s" +"Report bugs to <%s>.\n" +"The system catalogs might be corrupted." +"This grant will be dumped without GRANTED BY." +"Try \"%s --help\" for more information." +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"You are currently not connected to a database." +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%lld) does not match expected (%lld)" +"already connected to a database" +"archive is compressed, but this installation does not support compression (%s) -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"can only reopen input archives" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (%s)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression algorithm \"%s\" does not accept a compression level" +"compression algorithm \"%s\" does not accept a worker count" +"compression algorithm \"%s\" does not support long-distance mode" +"compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)" +"compression is not supported by tar archive format" +"compression option \"%s\" is not currently supported by pg_dump" +"compression option \"%s\" requires a value" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"corrupt tar header found in %s (expected %d, computed %d) file position %llu" +"could not alter table access method: %s" +"could not close LO data file: %m" +"could not close LOs TOC file: %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close directory \"%s\": %m" +"could not close file: %m" +"could not close filter file \"%s\": %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database" +"could not connect to database \"%s\"" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create LZ4 decompression context: %s" +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not create worker thread: %m" +"could not decompress data: %s" +"could not decompress: %s" +"could not determine seek position in archive file: %m" +"could not end compression: %s" +"could not end decompression: %s" +"could not execute command \"%s\": %m" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find a legal dump ordering for memberships in role \"%s\"" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not free LZ4 decompression context: %s" +"could not fsync file \"%s\": %m" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get server version" +"could not get server_version from libpq" +"could not identify dependency loop" +"could not initialize LZ4 compression: %s" +"could not initialize compression library" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open directory \"%s\": %m" +"could not open file \"%s\": %m" +"could not open filter file \"%s\": %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not open stdout for appending: %m" +"could not parse %s array" +"could not parse ACL list (%s) for parameter \"%s\"" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse index statistic columns" +"could not parse index statistic values" +"could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\": %m" +"could not read directory \"%s\": %m" +"could not read from command \"%s\": %m" +"could not read from filter file \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not rename file \"%s\" to \"%s\": %m" +"could not resolve dependency loop among these items:" +"could not resolve path \"%s\" to absolute form: %m" +"could not set \"default_table_access_method\": %s" +"could not set \"default_tablespace\" to %s: %s" +"could not set \"search_path\" to \"%s\": %s" +"could not set compression parameter \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not stat file \"%s\": %m" +"could not synchronize file system for file \"%s\": %m" +"could not uncompress data: %s" +"could not write to file: %m" +"could not write to file: %s" +"could not write to large object: %s" +"could not write to output file: %m" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"cross-database references are not implemented: %s" +"data block %d has wrong seek position" +"database name contains a newline or carriage return: \"%s\"\n" +"definition of view \"%s\" appears to be empty (length zero)" +"detail: " +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error during writing: %m" +"error during writing: %s" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"failed sanity check, table with OID %u not found" +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding extension tables" +"finding inheritance relationships" +"finding table check constraints" +"finding table default expressions" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found empty string where a compression option was expected" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"grant of role \"%s\" to \"%s\" has invalid grantor OID %s" +"hint: " +"identifying extension members" +"ignoring role grant for missing role with OID %s" +"ignoring role grant to missing role with OID %s" +"implied data-only restore" +"improper qualified name (too many dotted names): %s" +"improper relation name (too many dotted names): %s" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive" +"input file does not appear to be a valid archive (too short?)" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid binary \"%s\": %m" +"invalid client encoding \"%s\" specified" +"invalid collation \"%s\"" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression specification: %s" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid filter command (expected \"include\" or \"exclude\")" +"invalid format in filter read from file \"%s\" on line %d: %s" +"invalid format in filter read from standard input on line %d: %s" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid memory allocation request size %zu * %zu\n" +"invalid memory allocation request size %zu + %zu\n" +"invalid message received from worker: \"%s\"" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"invalid value \"%s\" for option %s" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"mismatched number of columns and values for index statistics" +"mismatched number of configurations and conditions for extension" +"missing filter object type" +"missing index for constraint \"%s\"" +"missing metadata for large objects \"%s\"" +"missing object name pattern" +"no data was returned by command \"%s\"" +"no filter command found (expected \"include\" or \"exclude\")" +"no matching extensions were found" +"no matching extensions were found for pattern \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"one of -d/--dbname and -f/--file must be specified" +"option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" +"option --if-exists requires option -c/--clean" +"option --include-foreign-data is not supported with parallel backup" +"option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" +"option --restrict-key can only be used with --format=plain" +"options -1/--single-transaction and --transaction-size cannot be used together" +"options -C/--create and -1/--single-transaction cannot be used together" +"options -c/--clean and -a/--data-only cannot be used together" +"options -d/--dbname and --restrict-key cannot be used together" +"options -d/--dbname and -f/--file cannot be used together" +"options -g/--globals-only and -r/--roles-only cannot be used together" +"options -g/--globals-only and -t/--tablespaces-only cannot be used together" +"options -r/--roles-only and -t/--tablespaces-only cannot be used together" +"options -s/--schema-only and --include-foreign-data cannot be used together" +"options -s/--schema-only and -a/--data-only cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"parallel backup only supported by the directory format" +"parallel dumps from standby servers are not supported by this server version" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: %s() failed: error code %d" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"postfix operators are not supported anymore (operator \"%s\")" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +"program \"%s\" was found by \"%s\" but was not the same version as %s" +"query failed: %s" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading indexes" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership of schemas" +"reading publication membership of tables" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscription membership of tables" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"reconnection failed: %s" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"role with OID %u does not exist" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving \"search_path = %s\"" +"saving \"standard_conforming_strings = %s\"" +"saving database definition" +"saving encoding = %s" +"saving large objects \"%s\"" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"server version: %s; %s version: %s" +"shell command argument contains a newline or carriage return: \"%s\"\n" +"skipping item %d %s %s" +"subscription with OID %u does not exist" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this build does not support compression with %s" +"this build does not support sync method \"%s\"" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unable to initialize LZ4 library: %s" +"unexpected COPY statement syntax: \"%s\"" +"unexpected column data for table \"%s\"" +"unexpected data offset flag %d" +"unexpected end of file" +"unexpected extra results during COPY of table \"%s\"" +"unexpected index data for table \"%s\"" +"unexpected policy command type: %c" +"unexpected section code %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from leader: \"%s\"" +"unrecognized compression algorithm: \"%s\"" +"unrecognized compression option: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized locale provider: %s" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %s" +"unrecognized sync method: %s" +"unrecognized table OID %u" +"unsupported filter object" +"unsupported filter object type: \"%.*s\"" +"unsupported pg_init_privs entry: %u %u %d" +"unsupported version (%d.%d) in file header" +"value for compression option \"%s\" must be a Boolean value" +"value for compression option \"%s\" must be an integer" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %zu byte of large object data (result = %d)" diff --git a/tools/pgmsg/testdata/REL_18_STABLE.txt b/tools/pgmsg/testdata/REL_18_STABLE.txt new file mode 100644 index 0000000..d0fe1ef --- /dev/null +++ b/tools/pgmsg/testdata/REL_18_STABLE.txt @@ -0,0 +1,585 @@ +# msgid set of src/bin/pg_dump/po/{de,fr}.po at REL_18_STABLE +# generated by tools/pgmsg; one Go-quoted msgid per line +"\nConnection options:\n" +"\nGeneral options:\n" +"\nIf -f/--file is not used, then the SQL script will be written to the standard\noutput.\n\n" +"\nIf no database name is supplied, then the PGDATABASE environment\nvariable value is used.\n\n" +"\nIf no input file name is supplied, then standard input is used.\n\n" +"\nOptions controlling the output content:\n" +"\nOptions controlling the restore:\n" +"\nThe options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\nmultiple times to select multiple objects.\n" +" %s [OPTION]...\n" +" %s [OPTION]... [DBNAME]\n" +" %s [OPTION]... [FILE]\n" +" --binary-upgrade for use by upgrade utilities only\n" +" --blobs (same as --large-objects, deprecated)\n" +" --column-inserts dump data as INSERT commands with column names\n" +" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" +" --disable-triggers disable triggers during data-only restore\n" +" --enable-row-security enable row security\n" +" --enable-row-security enable row security (dump only content user has\n access to)\n" +" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" +" --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +" --exclude-table-and-children=PATTERN\n do NOT dump the specified table(s), including\n child and partition tables\n" +" --exclude-table-data-and-children=PATTERN\n do NOT dump data for the specified table(s),\n including child and partition tables\n" +" --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" +" --extra-float-digits=NUM override default setting for extra_float_digits\n" +" --filter=FILENAME exclude databases based on expressions in FILENAME\n" +" --filter=FILENAME include or exclude objects and data from dump\n based on expressions in FILENAME\n" +" --filter=FILENAME restore or skip objects based on expressions\n in FILENAME\n" +" --if-exists use IF EXISTS when dropping objects\n" +" --include-foreign-data=PATTERN\n include data of foreign tables on foreign\n servers matching PATTERN\n" +" --inserts dump data as INSERT commands, rather than COPY\n" +" --load-via-partition-root load partitions via the root table\n" +" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" +" --no-blobs (same as --no-large-objects, deprecated)\n" +" --no-comments do not dump comment commands\n" +" --no-comments do not restore comment commands\n" +" --no-data do not dump data\n" +" --no-data do not restore data\n" +" --no-data-for-failed-tables do not restore data of tables that could not be\n created\n" +" --no-policies do not dump row security policies\n" +" --no-policies do not restore row security policies\n" +" --no-publications do not dump publications\n" +" --no-publications do not restore publications\n" +" --no-role-passwords do not dump passwords for roles\n" +" --no-schema do not dump schema\n" +" --no-schema do not restore schema\n" +" --no-security-labels do not dump security label assignments\n" +" --no-security-labels do not restore security labels\n" +" --no-statistics do not dump statistics\n" +" --no-statistics do not restore statistics\n" +" --no-subscriptions do not dump subscriptions\n" +" --no-subscriptions do not restore subscriptions\n" +" --no-sync do not wait for changes to be written safely to disk\n" +" --no-table-access-method do not dump table access methods\n" +" --no-table-access-method do not restore table access methods\n" +" --no-tablespaces do not dump tablespace assignments\n" +" --no-tablespaces do not restore tablespace assignments\n" +" --no-toast-compression do not dump TOAST compression methods\n" +" --no-unlogged-table-data do not dump unlogged table data\n" +" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" +" --quote-all-identifiers quote all identifiers, even if not key words\n" +" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n" +" --role=ROLENAME do SET ROLE before dump\n" +" --role=ROLENAME do SET ROLE before restore\n" +" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" +" --section=SECTION dump named section (pre-data, data, or post-data)\n" +" --section=SECTION restore named section (pre-data, data, or post-data)\n" +" --sequence-data include sequence data in dump\n" +" --serializable-deferrable wait until the dump can run without anomalies\n" +" --snapshot=SNAPSHOT use given snapshot for the dump\n" +" --statistics dump the statistics\n" +" --statistics restore the statistics\n" +" --statistics-only dump only the statistics, not schema or data\n" +" --statistics-only restore only the statistics, not schema or data\n" +" --strict-names require table and/or schema include patterns to\n match at least one entity each\n" +" --sync-method=METHOD set method for syncing files to disk\n" +" --table-and-children=PATTERN dump only the specified table(s), including\n child and partition tables\n" +" --transaction-size=N commit after every N objects\n" +" --use-set-session-authorization\n use SET SESSION AUTHORIZATION commands instead of\n ALTER OWNER commands to set ownership\n" +" -1, --single-transaction restore as a single transaction\n" +" -?, --help show this help, then exit\n" +" -?, --help show this help, then exit\n" +" -B, --no-large-objects exclude large objects in dump\n" +" -C, --create create the target database\n" +" -C, --create include commands to create database in dump\n" +" -E, --encoding=ENCODING dump the data in encoding ENCODING\n" +" -F, --format=c|d|t backup file format (should be automatic)\n" +" -F, --format=c|d|t|p output file format (custom, directory, tar,\n plain text (default))\n" +" -I, --index=NAME restore named index\n" +" -L, --use-list=FILENAME use table of contents from this file for\n selecting/ordering output\n" +" -N, --exclude-schema=NAME do not restore objects in this schema\n" +" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" +" -O, --no-owner skip restoration of object ownership\n" +" -O, --no-owner skip restoration of object ownership in\n plain-text format\n" +" -P, --function=NAME(args) restore named function\n" +" -S, --superuser=NAME superuser user name to use for disabling triggers\n" +" -S, --superuser=NAME superuser user name to use in plain-text format\n" +" -S, --superuser=NAME superuser user name to use in the dump\n" +" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" +" -T, --trigger=NAME restore named trigger\n" +" -U, --username=NAME connect as specified database user\n" +" -V, --version output version information, then exit\n" +" -V, --version output version information, then exit\n" +" -W, --password force password prompt (should happen automatically)\n" +" -Z, --compress=METHOD[:DETAIL]\n compress as specified\n" +" -a, --data-only dump only the data, not the schema or statistics\n" +" -a, --data-only restore only the data, no schema\n" +" -b, --large-objects include large objects in dump\n" +" -c, --clean clean (drop) database objects before recreating\n" +" -c, --clean clean (drop) databases before recreating\n" +" -d, --dbname=CONNSTR connect using connection string\n" +" -d, --dbname=DBNAME database to dump\n" +" -d, --dbname=NAME connect to database name\n" +" -e, --exit-on-error exit on error, default is to continue\n" +" -e, --extension=PATTERN dump the specified extension(s) only\n" +" -f, --file=FILENAME output file name\n" +" -f, --file=FILENAME output file or directory name\n" +" -f, --file=FILENAME output file name (- for stdout)\n" +" -g, --globals-only dump only global objects, no databases\n" +" -h, --host=HOSTNAME database server host or socket directory\n" +" -j, --jobs=NUM use this many parallel jobs to dump\n" +" -j, --jobs=NUM use this many parallel jobs to restore\n" +" -l, --database=DBNAME alternative default database\n" +" -l, --list print summarized TOC of the archive\n" +" -n, --schema=NAME restore only objects in this schema\n" +" -n, --schema=PATTERN dump the specified schema(s) only\n" +" -p, --port=PORT database server port number\n" +" -r, --roles-only dump only roles, no databases or tablespaces\n" +" -s, --schema-only dump only the schema, no data or statistics\n" +" -s, --schema-only restore only the schema, no data\n" +" -t, --table=NAME restore named relation (table, view, etc.)\n" +" -t, --table=PATTERN dump only the specified table(s)\n" +" -t, --tablespaces-only dump only tablespaces, no databases or roles\n" +" -v, --verbose verbose mode\n" +" -v, --verbose verbose mode\n" +" -w, --no-password never prompt for password\n" +" -x, --no-privileges do not dump privileges (grant/revoke)\n" +" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" +"%s" +"%s exports a PostgreSQL database as an SQL script or to other formats.\n\n" +"%s exports a PostgreSQL database cluster as an SQL script.\n\n" +"%s filter for \"%s\" is not allowed" +"%s home page: <%s>\n" +"%s must be in range %d..%d" +"%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" +"%s() failed: %m" +"%s() failed: error code %d" +"%s: %sCommand was: %s" +"COPY failed for table \"%s\": %s" +"Command was: %s" +"Consider using a full dump instead of a --data-only dump to avoid this problem." +"Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." +"Dumping the contents of table \"%s\" failed: PQgetResult() failed." +"Error message from server: %s" +"Password: " +"Query was: %s" +"Report bugs to <%s>.\n" +"The system catalogs might be corrupted." +"This grant will be dumped without GRANTED BY." +"Try \"%s --help\" for more information." +"Usage:\n" +"WITH OIDS is not supported anymore (table \"%s\")" +"You are currently not connected to a database." +"You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." +"a worker process died unexpectedly" +"aborting because of server version mismatch" +"actual file length (%lld) does not match expected (%lld)" +"already connected to a database" +"archive format \"%s\" is not supported; please use psql" +"archive is compressed, but this installation does not support compression (%s) -- no data will be available" +"archive items not in correct section order" +"archive was made on a machine with larger integers, some operations might fail" +"bad dumpId" +"bad table dumpId for TABLE DATA item" +"bogus transform definition, at least one of trffromsql and trftosql should be nonzero" +"bogus value in pg_cast.castfunc or pg_cast.castmethod field" +"bogus value in pg_cast.castmethod field" +"bogus value in pg_transform.trffromsql field" +"bogus value in pg_transform.trftosql field" +"can only reopen input archives" +"cannot dump statistics for relation kind \"%c\"" +"cannot duplicate null pointer (internal error)\n" +"cannot restore from compressed archive (%s)" +"cannot specify both --single-transaction and multiple jobs" +"child process exited with exit code %d" +"child process exited with unrecognized status %d" +"child process was terminated by exception 0x%X" +"child process was terminated by signal %d: %s" +"command not executable" +"command not found" +"compression algorithm \"%s\" does not accept a compression level" +"compression algorithm \"%s\" does not accept a worker count" +"compression algorithm \"%s\" does not support long-distance mode" +"compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)" +"compression is not supported by tar archive format" +"compression option \"%s\" is not currently supported by pg_dump" +"compression option \"%s\" requires a value" +"compressor active" +"connecting to database for restore" +"connecting to new database \"%s\"" +"corrupt tar header found in %s (expected %d, computed %d) file position %llu" +"could not alter table access method: %s" +"could not change permissions of directory \"%s\": %m" +"could not close LO data file: %m" +"could not close LOs TOC file: %m" +"could not close TOC file: %m" +"could not close archive file: %m" +"could not close compression library: %s" +"could not close compression stream: %s" +"could not close data file \"%s\": %m" +"could not close data file: %m" +"could not close file: %m" +"could not close filter file \"%s\": %m" +"could not close input file: %m" +"could not close large object TOC file \"%s\": %m" +"could not close output file: %m" +"could not close temporary file: %m" +"could not commit database transaction" +"could not compress data: %s" +"could not connect to database \"%s\"" +"could not connect to databases \"postgres\" or \"template1\"\nPlease specify an alternative database." +"could not create LZ4 decompression context: %s" +"could not create communication channels: %m" +"could not create directory \"%s\": %m" +"could not create large object %u: %s" +"could not create worker process: %m" +"could not create worker thread: %m" +"could not decompress data: %s" +"could not decompress: %s" +"could not determine seek position in archive file: %m" +"could not end compression: %s" +"could not end decompression: %s" +"could not execute command \"%s\": %m" +"could not execute query" +"could not find a \"%s\" to execute" +"could not find a legal dump ordering for memberships in role \"%s\"" +"could not find block ID %d in archive -- possibly corrupt archive" +"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" +"could not find entry for ID %d" +"could not find file \"%s\" in archive" +"could not find function definition for function with OID %u" +"could not find header for file \"%s\" in tar archive" +"could not find index attname \"%s\"" +"could not find operator with OID %s" +"could not find parent extension for %s %s" +"could not find referenced extension %u" +"could not find where to insert IF EXISTS in statement \"%s\"" +"could not free LZ4 decompression context: %s" +"could not fsync file \"%s\": %m" +"could not generate restrict key" +"could not generate temporary file name: %m" +"could not get \"server_version\" from libpq" +"could not get server version" +"could not identify dependency loop" +"could not initialize LZ4 compression: %s" +"could not initialize compression library" +"could not initialize compression library: %s" +"could not obtain lock on relation \"%s\"\nThis 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." +"could not open TOC file \"%s\" for input: %m" +"could not open TOC file \"%s\" for output: %m" +"could not open TOC file \"%s\": %m" +"could not open TOC file for input: %m" +"could not open TOC file for output: %m" +"could not open directory \"%s\": %m" +"could not open file \"%s\": %m" +"could not open filter file \"%s\": %m" +"could not open input file \"%s\": %m" +"could not open input file: %m" +"could not open large object %u: %s" +"could not open large object TOC file \"%s\" for input: %m" +"could not open output file \"%s\": %m" +"could not open output file: %m" +"could not open stdout for appending: %m" +"could not parse %s array" +"could not parse ACL list (%s) for parameter \"%s\"" +"could not parse ACL list (%s) for tablespace \"%s\"" +"could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse default ACL list (%s)" +"could not parse index statistic columns" +"could not parse index statistic values" +"could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" +"could not parse numeric array \"%s\": invalid character in number" +"could not parse numeric array \"%s\": too many numbers" +"could not parse result of current_schemas()" +"could not parse server version \"%s\"" +"could not re-open the output file \"%s\": %m" +"could not read binary \"%s\": %m" +"could not read directory \"%s\": %m" +"could not read from command \"%s\": %m" +"could not read from filter file \"%s\": %m" +"could not read from input file: %m" +"could not read from input file: %s" +"could not read from input file: end of file" +"could not read input file: %m" +"could not rename file \"%s\" to \"%s\": %m" +"could not resolve dependency loop among these items:" +"could not resolve path \"%s\" to absolute form: %m" +"could not set \"default_table_access_method\": %s" +"could not set \"default_tablespace\" to %s: %s" +"could not set \"search_path\" to \"%s\": %s" +"could not set compression parameter \"%s\": %s" +"could not set seek position in archive file: %m" +"could not set session user to \"%s\": %s" +"could not start database transaction" +"could not stat file \"%s\": %m" +"could not synchronize file system for file \"%s\": %m" +"could not uncompress data: %s" +"could not write to file: %m" +"could not write to file: %s" +"could not write to large object: %s" +"could not write to output file: %m" +"could not write to the communication channel: %m" +"creating %s \"%s\"" +"creating %s \"%s.%s\"" +"cross-database references are not implemented: %s" +"data block %d has wrong seek position" +"database name contains a newline or carriage return: \"%s\"\n" +"definition of view \"%s\" appears to be empty (length zero)" +"detail: " +"did not find magic string in file header" +"direct database connections are not supported in pre-1.3 archives" +"directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" +"directory \"%s\" is not empty" +"directory name too long: \"%s\"" +"disabling triggers for %s" +"don't know how to set owner for object type \"%s\"" +"dropping %s %s" +"dumping contents of table \"%s.%s\"" +"dumping database \"%s\"" +"enabling triggers for %s" +"entering main parallel loop" +"entry ID %d out of range -- perhaps a corrupt TOC" +"error during file seek: %m" +"error during writing: %m" +"error during writing: %s" +"error reading large object %u: %s" +"error reading large object TOC file \"%s\"" +"error returned by PQputCopyData: %s" +"error returned by PQputCopyEnd: %s" +"error: " +"errors ignored on restore: %d" +"excluding database \"%s\"" +"executing %s" +"executing %s %s" +"expected %d check constraint on table \"%s\" but found %d" +"expected format (%d) differs from format found in file (%d)" +"failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" +"failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" +"failed sanity check, parent table with OID %u of sequence with OID %u not found" +"failed sanity check, table OID %u appearing in pg_partitioned_table not found" +"failed sanity check, table with OID %u not found" +"failed to get data for sequence \"%s\"; user may lack SELECT privilege on the sequence or the sequence may have been concurrently dropped" +"file name too long: \"%s\"" +"file offset in dump file is too large" +"finding extension tables" +"finding inheritance relationships" +"finding invalid not-null constraints" +"finding table check constraints" +"finding table default expressions" +"finished item %d %s %s" +"finished main parallel loop" +"flagging indexes in partitioned tables" +"flagging inherited columns in subtables" +"found empty string where a compression option was expected" +"found unexpected block ID (%d) when reading data -- expected %d" +"from TOC entry %d; %u %u %s %s %s" +"function \"%s\" not found" +"grant of role \"%s\" to \"%s\" has invalid grantor OID %s" +"hint: " +"identifying extension members" +"ignoring role grant for missing role with OID %s" +"ignoring role grant to missing role with OID %s" +"implied no-schema restore" +"improper qualified name (too many dotted names): %s" +"improper relation name (too many dotted names): %s" +"incomplete tar header found (%lu byte)" +"index \"%s\" not found" +"input file appears to be a text format dump. Please use psql." +"input file does not appear to be a valid archive (too short?)" +"input file does not appear to be a valid tar archive" +"input file is too short (read %lu, expected 5)" +"internal error -- WriteData cannot be called outside the context of a DataDumper routine" +"invalid ENCODING item: %s" +"invalid OID for large object" +"invalid OID for large object (%u)" +"invalid STDSTRINGS item: %s" +"invalid adnum value %d for table \"%s\"" +"invalid binary \"%s\": %m" +"invalid client encoding \"%s\" specified" +"invalid collation \"%s\"" +"invalid column number %d for table \"%s\"" +"invalid column numbering in table \"%s\"" +"invalid compression specification: %s" +"invalid creation date in header" +"invalid dependency %d" +"invalid dumpId %d" +"invalid filter command (expected \"include\" or \"exclude\")" +"invalid format in filter read from file \"%s\" on line %d: %s" +"invalid format in filter read from standard input on line %d: %s" +"invalid line in large object TOC file \"%s\": \"%s\"" +"invalid memory allocation request size %zu * %zu\n" +"invalid memory allocation request size %zu + %zu\n" +"invalid message received from worker: \"%s\"" +"invalid number of parents %d for table \"%s\"" +"invalid output format \"%s\" specified" +"invalid restrict key" +"invalid type \"%c\" of access method \"%s\"" +"invalid value \"%s\" for option %s" +"large-object output not supported in chosen format" +"last built-in OID is %u" +"launching item %d %s %s" +"line ignored: %s" +"mismatched number of columns and values for index statistics" +"mismatched number of configurations and conditions for extension" +"missing filter object type" +"missing index for constraint \"%s\"" +"missing metadata for large objects \"%s\"" +"missing object name pattern" +"no data was returned by command \"%s\"" +"no filter command found (expected \"include\" or \"exclude\")" +"no matching extensions were found" +"no matching extensions were found for pattern \"%s\"" +"no matching foreign servers were found for pattern \"%s\"" +"no matching schemas were found" +"no matching schemas were found for pattern \"%s\"" +"no matching tables were found" +"no matching tables were found for pattern \"%s\"" +"no output directory specified" +"no referenced object %u %u" +"no referencing object %u %u" +"one of -d/--dbname and -f/--file must be specified" +"option %s can only be used with %s" +"option %s cannot be used together with %s, %s, or %s" +"option %s is not supported with parallel backup" +"option %s requires option %s" +"option %s requires option %s, %s, or %s" +"options %s and %s cannot be used together" +"out of memory" +"out of memory\n" +"out of on_exit_nicely slots" +"parallel backup only supported by the directory format" +"parallel dumps from standby servers are not supported by this server version" +"parallel restore from non-seekable file is not supported" +"parallel restore from standard input is not supported" +"parallel restore is not supported with archives made by pre-8.0 pg_dump" +"parallel restore is not supported with this archive file format" +"pg_dump failed on database \"%s\", exiting" +"pgpipe: %s() failed: error code %d" +"pgpipe: could not accept connection: error code %d" +"pgpipe: could not bind: error code %d" +"pgpipe: could not connect socket: error code %d" +"pgpipe: could not create second socket: error code %d" +"pgpipe: could not create socket: error code %d" +"pgpipe: could not listen: error code %d" +"postfix operators are not supported anymore (operator \"%s\")" +"processing %s" +"processing data for table \"%s.%s\"" +"processing item %d %s %s" +"processing missed item %d %s %s" +"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +"program \"%s\" was found by \"%s\" but was not the same version as %s" +"query failed: %s" +"query returned %d row instead of one: %s" +"query to get data of sequence \"%s\" returned %d row (expected 1)" +"query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" +"query to obtain definition of view \"%s\" returned more than one definition" +"query to obtain definition of view \"%s\" returned no data" +"reading column info for interesting tables" +"reading constraints" +"reading default privileges" +"reading dependency data" +"reading event triggers" +"reading extended statistics" +"reading extensions" +"reading indexes" +"reading large objects" +"reading partitioning data" +"reading policies" +"reading procedural languages" +"reading publication membership of schemas" +"reading publication membership of tables" +"reading publications" +"reading rewrite rules" +"reading row-level security policies" +"reading schemas" +"reading subscription membership of tables" +"reading subscriptions" +"reading table inheritance information" +"reading transforms" +"reading triggers" +"reading type casts" +"reading user-defined access methods" +"reading user-defined aggregate functions" +"reading user-defined collations" +"reading user-defined conversions" +"reading user-defined foreign servers" +"reading user-defined foreign-data wrappers" +"reading user-defined functions" +"reading user-defined operator classes" +"reading user-defined operator families" +"reading user-defined operators" +"reading user-defined tables" +"reading user-defined text search configurations" +"reading user-defined text search dictionaries" +"reading user-defined text search parsers" +"reading user-defined text search templates" +"reading user-defined types" +"restored %d large object" +"restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." +"restoring large object with OID %u" +"restoring tables WITH OIDS is not supported anymore" +"role name starting with \"pg_\" skipped (%s)" +"role with OID %u does not exist" +"running \"%s\"" +"sanity check on integer size (%lu) failed" +"saving \"search_path = %s\"" +"saving \"standard_conforming_strings = %s\"" +"saving database definition" +"saving encoding = %s" +"saving large objects \"%s\"" +"schema \"%s\" not found" +"schema with OID %u does not exist" +"server version: %s; %s version: %s" +"shell command argument contains a newline or carriage return: \"%s\"\n" +"skipping item %d %s %s" +"statistics dumped out of order (current: %d %s %s, expected: %d %s %s)" +"subscription with OID %u does not exist" +"subscriptions not dumped because current user is not a superuser" +"table \"%s\" could not be created, will not restore its data" +"table \"%s\" not found" +"there are circular foreign-key constraints on this table:" +"this build does not support compression with %s" +"this build does not support sync method \"%s\"" +"this format cannot be read" +"too many command-line arguments (first is \"%s\")" +"trigger \"%s\" not found" +"typtype of data type \"%s\" appears to be invalid" +"unable to initialize LZ4 library: %s" +"unexpected COPY statement syntax: \"%s\"" +"unexpected TOC entry in WriteToc(): %d %s %s" +"unexpected TOC entry in _printTocEntry(): %d %s %s" +"unexpected column data for table \"%s\"" +"unexpected data offset flag %d" +"unexpected end of file" +"unexpected extra results during COPY of table \"%s\"" +"unexpected index data for table \"%s\"" +"unexpected null attname" +"unexpected policy command type: %c" +"unexpected section code %d" +"unrecognized aggfinalmodify value for aggregate \"%s\"" +"unrecognized aggmfinalmodify value for aggregate \"%s\"" +"unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" +"unrecognized collation provider: %s" +"unrecognized command received from leader: \"%s\"" +"unrecognized compression algorithm: \"%s\"" +"unrecognized compression option: \"%s\"" +"unrecognized constraint type: %c" +"unrecognized data block type %d while restoring archive" +"unrecognized data block type (%d) while searching archive" +"unrecognized encoding \"%s\"" +"unrecognized file format \"%d\"" +"unrecognized locale provider: %s" +"unrecognized object type in default privileges: %d" +"unrecognized proparallel value for function \"%s\"" +"unrecognized provolatile value for function \"%s\"" +"unrecognized section name: \"%s\"" +"unrecognized sequence type: %d" +"unrecognized sequence type: %s" +"unrecognized sync method: %s" +"unrecognized table OID %u" +"unsupported filter object" +"unsupported filter object type: \"%.*s\"" +"unsupported pg_init_privs entry: %u %u %d" +"unsupported version (%d.%d) in file header" +"value for compression option \"%s\" must be a Boolean value" +"value for compression option \"%s\" must be an integer" +"warning from original dump file: %s" +"warning: " +"while FINALIZING:" +"while INITIALIZING:" +"while PROCESSING TOC:" +"worker process failed: exit code %d" +"wrong number of fields retrieved from table \"%s\"" +"wrote %zu byte of large object data (result = %d)"